1 /*
2 * Copyright (c) 2013 Andrew Kelley
3 *
4 * This file is part of libgroove, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8 #include "encoder.h"
9 #include "queue.h"
10 #include "buffer.h"
11
12 #include <libavutil/mem.h>
13 #include <libavutil/log.h>
14 #include <libavutil/channel_layout.h>
15 #include <libavutil/dict.h>
16 #include <libavcodec/avcodec.h>
17 #include <libavformat/avformat.h>
18 #include <libavformat/avio.h>
19 #include <string.h>
20 #include <pthread.h>
21
22 struct GrooveEncoderPrivate {
23 struct GrooveEncoder externals;
24 struct GrooveQueue *audioq;
25 struct GrooveSink *sink;
26 AVFormatContext *fmt_ctx;
27 AVOutputFormat *oformat;
28 AVCodec *codec;
29 AVStream *stream;
30 AVPacket pkt;
31 int audioq_size; // in bytes
32 int abort_request;
33
34 // set temporarily
35 struct GroovePlaylistItem *purge_item;
36
37 // encode_head_mutex applies to variables inside this block.
38 pthread_mutex_t encode_head_mutex;
39 char encode_head_mutex_inited;
40 // encode_thread waits on this when the encoded audio buffer queue
41 // is full.
42 pthread_cond_t drain_cond;
43 char drain_cond_inited;
44 struct GroovePlaylistItem *encode_head;
45 double encode_pos;
46 uint64_t encode_pts;
47
48 struct GrooveAudioFormat encode_format;
49
50 pthread_t thread_id;
51
52 AVIOContext *avio;
53 unsigned char *avio_buf;
54
55 int sent_header;
56 char strbuf[512];
57
58 AVDictionary *metadata;
59
60 uint64_t next_pts;
61 };
62
63 static struct GrooveBuffer *end_of_q_sentinel = NULL;
64
encode_buffer(struct GrooveEncoder * encoder,struct GrooveBuffer * buffer)65 static int encode_buffer(struct GrooveEncoder *encoder, struct GrooveBuffer *buffer) {
66 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
67
68 av_init_packet(&e->pkt);
69
70 AVFrame *frame = NULL;
71 if (buffer) {
72 e->encode_head = buffer->item;
73 e->encode_pos = buffer->pos;
74 e->encode_format = buffer->format;
75
76 struct GrooveBufferPrivate *b = (struct GrooveBufferPrivate *) buffer;
77 frame = b->frame;
78 frame->pts = e->next_pts;
79 e->encode_pts = e->next_pts;
80 e->next_pts += buffer->frame_count + 1;
81 }
82
83 int got_packet = 0;
84 int errcode = avcodec_encode_audio2(e->stream->codec, &e->pkt, frame, &got_packet);
85 if (errcode < 0) {
86 av_strerror(errcode, e->strbuf, sizeof(e->strbuf));
87 av_log(NULL, AV_LOG_ERROR, "error encoding audio frame: %s\n", e->strbuf);
88 return -1;
89 }
90 if (!got_packet)
91 return -1;
92
93 av_write_frame(e->fmt_ctx, &e->pkt);
94 av_free_packet(&e->pkt);
95
96 return 0;
97 }
98
cleanup_avcontext(struct GrooveEncoderPrivate * e)99 static void cleanup_avcontext(struct GrooveEncoderPrivate *e) {
100 if (e->stream) {
101 avcodec_close(e->stream->codec);
102 // stream is freed by freeing the AVFormatContext
103 e->stream = NULL;
104 }
105
106 if (e->fmt_ctx) {
107 avformat_free_context(e->fmt_ctx);
108 e->fmt_ctx = NULL;
109 }
110
111 e->sent_header = 0;
112 e->encode_head = NULL;
113 e->encode_pos = -1.0;
114 e->encode_pts = 0;
115 e->next_pts = 0;
116 }
117
init_avcontext(struct GrooveEncoder * encoder)118 static int init_avcontext(struct GrooveEncoder *encoder) {
119 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
120 e->fmt_ctx = avformat_alloc_context();
121 if (!e->fmt_ctx) {
122 av_log(NULL, AV_LOG_ERROR, "unable to allocate format context\n");
123 return -1;
124 }
125 e->fmt_ctx->pb = e->avio;
126 e->fmt_ctx->oformat = e->oformat;
127
128 e->stream = avformat_new_stream(e->fmt_ctx, e->codec);
129 if (!e->stream) {
130 av_log(NULL, AV_LOG_ERROR, "unable to create output stream\n");
131 return -1;
132 }
133
134 AVCodecContext *codec_ctx = e->stream->codec;
135 codec_ctx->bit_rate = encoder->bit_rate;
136 codec_ctx->sample_fmt = (enum AVSampleFormat)encoder->actual_audio_format.sample_fmt;
137 codec_ctx->sample_rate = encoder->actual_audio_format.sample_rate;
138 codec_ctx->channel_layout = encoder->actual_audio_format.channel_layout;
139 codec_ctx->channels = av_get_channel_layout_nb_channels(encoder->actual_audio_format.channel_layout);
140 codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
141
142 int err = avcodec_open2(codec_ctx, e->codec, NULL);
143 if (err < 0) {
144 av_strerror(err, e->strbuf, sizeof(e->strbuf));
145 av_log(NULL, AV_LOG_ERROR, "unable to open codec: %s\n", e->strbuf);
146 return -1;
147 }
148 e->stream->codec = codec_ctx;
149
150 return 0;
151 }
152
encode_thread(void * arg)153 static void *encode_thread(void *arg) {
154 struct GrooveEncoder *encoder = arg;
155 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
156
157 struct GrooveBuffer *buffer;
158 while (!e->abort_request) {
159 pthread_mutex_lock(&e->encode_head_mutex);
160
161 if (e->audioq_size >= encoder->encoded_buffer_size) {
162 pthread_cond_wait(&e->drain_cond, &e->encode_head_mutex);
163 pthread_mutex_unlock(&e->encode_head_mutex);
164 continue;
165 }
166
167 // we definitely want to unlock the mutex while we wait for the
168 // next buffer. Otherwise there will be a deadlock when sink_flush or
169 // sink_purge is called.
170 pthread_mutex_unlock(&e->encode_head_mutex);
171
172 int result = groove_sink_buffer_get(e->sink, &buffer, 1);
173
174 pthread_mutex_lock(&e->encode_head_mutex);
175
176 if (result == GROOVE_BUFFER_END) {
177 // flush encoder with empty packets
178 while (encode_buffer(encoder, NULL) >= 0) {}
179 // then flush format context with empty packets
180 while (av_write_frame(e->fmt_ctx, NULL) == 0) {}
181
182 // send trailer
183 avio_flush(e->avio);
184 av_log(NULL, AV_LOG_INFO, "encoder: writing trailer\n");
185 if (av_write_trailer(e->fmt_ctx) < 0) {
186 av_log(NULL, AV_LOG_ERROR, "could not write trailer\n");
187 }
188 avio_flush(e->avio);
189
190 groove_queue_put(e->audioq, end_of_q_sentinel);
191
192 cleanup_avcontext(e);
193 init_avcontext(encoder);
194
195 pthread_mutex_unlock(&e->encode_head_mutex);
196 continue;
197 }
198
199 if (result != GROOVE_BUFFER_YES) {
200 pthread_mutex_unlock(&e->encode_head_mutex);
201 break;
202 }
203
204 if (!e->sent_header) {
205 avio_flush(e->avio);
206
207 // copy metadata to format context
208 av_dict_free(&e->fmt_ctx->metadata);
209 AVDictionaryEntry *tag = NULL;
210 while((tag = av_dict_get(e->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
211 av_dict_set(&e->fmt_ctx->metadata, tag->key, tag->value, AV_DICT_IGNORE_SUFFIX);
212 }
213
214 av_log(NULL, AV_LOG_INFO, "encoder: writing header\n");
215 if (avformat_write_header(e->fmt_ctx, NULL) < 0) {
216 av_log(NULL, AV_LOG_ERROR, "could not write header\n");
217 }
218 avio_flush(e->avio);
219 e->sent_header = 1;
220 }
221
222 encode_buffer(encoder, buffer);
223 pthread_mutex_unlock(&e->encode_head_mutex);
224 groove_buffer_unref(buffer);
225 }
226 return NULL;
227 }
228
sink_purge(struct GrooveSink * sink,struct GroovePlaylistItem * item)229 static void sink_purge(struct GrooveSink *sink, struct GroovePlaylistItem *item) {
230 struct GrooveEncoder *encoder = sink->userdata;
231 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
232
233 pthread_mutex_lock(&e->encode_head_mutex);
234 e->purge_item = item;
235 groove_queue_purge(e->audioq);
236 e->purge_item = NULL;
237
238 if (e->encode_head == item) {
239 e->encode_head = NULL;
240 e->encode_pos = -1.0;
241 }
242 pthread_cond_signal(&e->drain_cond);
243 pthread_mutex_unlock(&e->encode_head_mutex);
244 }
245
sink_flush(struct GrooveSink * sink)246 static void sink_flush(struct GrooveSink *sink) {
247 struct GrooveEncoder *encoder = sink->userdata;
248 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
249
250 pthread_mutex_lock(&e->encode_head_mutex);
251 groove_queue_flush(e->audioq);
252
253 cleanup_avcontext(e);
254 init_avcontext(encoder);
255 groove_queue_put(e->audioq, end_of_q_sentinel);
256
257 pthread_cond_signal(&e->drain_cond);
258 pthread_mutex_unlock(&e->encode_head_mutex);
259 }
260
audioq_purge(struct GrooveQueue * queue,void * obj)261 static int audioq_purge(struct GrooveQueue* queue, void *obj) {
262 struct GrooveBuffer *buffer = obj;
263 if (buffer == end_of_q_sentinel)
264 return 0;
265 struct GrooveEncoderPrivate *e = queue->context;
266 return buffer->item == e->purge_item;
267 }
268
audioq_cleanup(struct GrooveQueue * queue,void * obj)269 static void audioq_cleanup(struct GrooveQueue* queue, void *obj) {
270 struct GrooveBuffer *buffer = obj;
271 if (buffer == end_of_q_sentinel)
272 return;
273 struct GrooveEncoderPrivate *e = queue->context;
274 e->audioq_size -= buffer->size;
275 groove_buffer_unref(buffer);
276 }
277
audioq_put(struct GrooveQueue * queue,void * obj)278 static void audioq_put(struct GrooveQueue *queue, void *obj) {
279 struct GrooveBuffer *buffer = obj;
280 if (buffer == end_of_q_sentinel)
281 return;
282 struct GrooveEncoderPrivate *e = queue->context;
283 e->audioq_size += buffer->size;
284 }
285
audioq_get(struct GrooveQueue * queue,void * obj)286 static void audioq_get(struct GrooveQueue *queue, void *obj) {
287 struct GrooveBuffer *buffer = obj;
288 if (buffer == end_of_q_sentinel)
289 return;
290 struct GrooveEncoderPrivate *e = queue->context;
291 struct GrooveEncoder *encoder = &e->externals;
292 e->audioq_size -= buffer->size;
293
294 if (e->audioq_size < encoder->encoded_buffer_size)
295 pthread_cond_signal(&e->drain_cond);
296 }
297
encoder_write_packet(void * opaque,uint8_t * buf,int buf_size)298 static int encoder_write_packet(void *opaque, uint8_t *buf, int buf_size) {
299 struct GrooveEncoderPrivate *e = opaque;
300
301 struct GrooveBufferPrivate *b = av_mallocz(sizeof(struct GrooveBufferPrivate));
302
303 if (!b) {
304 av_log(NULL, AV_LOG_ERROR, "unable to allocate buffer\n");
305 return -1;
306 }
307
308 struct GrooveBuffer *buffer = &b->externals;
309
310 if (pthread_mutex_init(&b->mutex, NULL) != 0) {
311 av_free(b);
312 av_log(NULL, AV_LOG_ERROR, "unable to create mutex\n");
313 return -1;
314 }
315
316 buffer->item = e->encode_head;
317 buffer->pos = e->encode_pos;
318 buffer->pts = e->encode_pts;
319 buffer->format = e->encode_format;
320
321 b->is_packet = 1;
322 b->data = av_malloc(buf_size);
323 if (!b->data) {
324 av_free(buffer);
325 av_free(b);
326 pthread_mutex_destroy(&b->mutex);
327 av_log(NULL, AV_LOG_ERROR, "unable to create data buffer\n");
328 return -1;
329 }
330 memcpy(b->data, buf, buf_size);
331
332 buffer->data = &b->data;
333 buffer->size = buf_size;
334
335 b->ref_count = 1;
336
337 groove_queue_put(e->audioq, buffer);
338
339 return 0;
340 }
341
groove_encoder_create(void)342 struct GrooveEncoder *groove_encoder_create(void) {
343 struct GrooveEncoderPrivate *e = av_mallocz(sizeof(struct GrooveEncoderPrivate));
344
345 if (!e) {
346 av_log(NULL, AV_LOG_ERROR, "unable to allocate encoder\n");
347 return NULL;
348 }
349 struct GrooveEncoder *encoder = &e->externals;
350
351 const int buffer_size = 4 * 1024;
352 e->avio_buf = av_malloc(buffer_size);
353 if (!e->avio_buf) {
354 groove_encoder_destroy(encoder);
355 av_log(NULL, AV_LOG_ERROR, "unable to allocate avio buffer\n");
356 return NULL;
357 }
358
359 e->avio = avio_alloc_context(e->avio_buf, buffer_size, 1, encoder, NULL,
360 encoder_write_packet, NULL);
361 if (!e->avio) {
362 groove_encoder_destroy(encoder);
363 av_log(NULL, AV_LOG_ERROR, "unable to allocate avio context\n");
364 return NULL;
365 }
366
367 if (pthread_mutex_init(&e->encode_head_mutex, NULL) != 0) {
368 groove_encoder_destroy(encoder);
369 av_log(NULL, AV_LOG_ERROR, "unable to create mutex\n");
370 return NULL;
371 }
372 e->encode_head_mutex_inited = 1;
373
374 if (pthread_cond_init(&e->drain_cond, NULL) != 0) {
375 groove_encoder_destroy(encoder);
376 av_log(NULL, AV_LOG_ERROR, "unable to create mutex condition\n");
377 return NULL;
378 }
379 e->drain_cond_inited = 1;
380
381 e->audioq = groove_queue_create();
382 if (!e->audioq) {
383 groove_encoder_destroy(encoder);
384 av_log(NULL, AV_LOG_ERROR, "unable to allocate queue\n");
385 return NULL;
386 }
387 e->audioq->context = encoder;
388 e->audioq->cleanup = audioq_cleanup;
389 e->audioq->put = audioq_put;
390 e->audioq->get = audioq_get;
391 e->audioq->purge = audioq_purge;
392
393 e->sink = groove_sink_create();
394 if (!e->sink) {
395 groove_encoder_destroy(encoder);
396 av_log(NULL, AV_LOG_ERROR, "unable to allocate sink\n");
397 return NULL;
398 }
399
400 e->sink->userdata = encoder;
401 e->sink->purge = sink_purge;
402 e->sink->flush = sink_flush;
403
404 // set some defaults
405 encoder->bit_rate = 256 * 1000;
406 encoder->target_audio_format.sample_rate = 44100;
407 encoder->target_audio_format.sample_fmt = GROOVE_SAMPLE_FMT_S16;
408 encoder->target_audio_format.channel_layout = GROOVE_CH_LAYOUT_STEREO;
409 encoder->sink_buffer_size = e->sink->buffer_size;
410 encoder->encoded_buffer_size = 16 * 1024;
411 encoder->gain = e->sink->gain;
412
413 return encoder;
414 }
415
groove_encoder_destroy(struct GrooveEncoder * encoder)416 void groove_encoder_destroy(struct GrooveEncoder *encoder) {
417 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
418
419 if (e->sink)
420 groove_sink_destroy(e->sink);
421
422 if (e->audioq)
423 groove_queue_destroy(e->audioq);
424
425 if (e->encode_head_mutex_inited)
426 pthread_mutex_destroy(&e->encode_head_mutex);
427
428 if (e->drain_cond_inited)
429 pthread_cond_destroy(&e->drain_cond);
430
431 if (e->avio)
432 av_free(e->avio);
433
434 if (e->avio_buf)
435 av_free(e->avio_buf);
436
437 if (e->metadata)
438 av_dict_free(&e->metadata);
439
440 av_free(e);
441 }
442
abs_diff(int a,int b)443 static int abs_diff(int a, int b) {
444 int n = a - b;
445 return n >= 0 ? n : -n;
446 }
447
codec_supports_fmt(AVCodec * codec,enum GrooveSampleFormat fmt)448 static int codec_supports_fmt(AVCodec *codec, enum GrooveSampleFormat fmt) {
449 const enum GrooveSampleFormat *p = (enum GrooveSampleFormat*) codec->sample_fmts;
450
451 while (*p != GROOVE_SAMPLE_FMT_NONE) {
452 if (*p == fmt)
453 return 1;
454 p += 1;
455 }
456
457 return 0;
458 }
459
closest_supported_sample_fmt(AVCodec * codec,enum GrooveSampleFormat target)460 static enum GrooveSampleFormat closest_supported_sample_fmt(AVCodec *codec,
461 enum GrooveSampleFormat target)
462 {
463 // if we can, return exact match. otherwise, return the format with the
464 // next highest sample byte count
465
466 if (!codec->sample_fmts)
467 return target;
468
469 int target_size = av_get_bytes_per_sample((enum AVSampleFormat)target);
470 const enum GrooveSampleFormat *p = (enum GrooveSampleFormat*) codec->sample_fmts;
471 enum GrooveSampleFormat best = *p;
472 int best_size = av_get_bytes_per_sample((enum AVSampleFormat)best);
473 while (*p != GROOVE_SAMPLE_FMT_NONE) {
474 if (*p == target)
475 return target;
476
477 int size = av_get_bytes_per_sample((enum AVSampleFormat)*p);
478 if ((best_size < target_size && size > best_size) ||
479 (size >= target_size &&
480 abs_diff(target_size, size) < abs_diff(target_size, best_size)))
481 {
482 best_size = size;
483 best = *p;
484 }
485
486 p += 1;
487 }
488
489 // prefer interleaved format
490 enum GrooveSampleFormat packed_best = (enum GrooveSampleFormat)av_get_packed_sample_fmt((enum AVSampleFormat)best);
491 return codec_supports_fmt(codec, packed_best) ? packed_best : best;
492 }
493
closest_supported_sample_rate(AVCodec * codec,int target)494 static int closest_supported_sample_rate(AVCodec *codec, int target) {
495 // if we can, return exact match. otherwise, return the minimum sample
496 // rate >= target
497
498 if (!codec->supported_samplerates)
499 return target;
500
501 const int *p = codec->supported_samplerates;
502 int best = *p;
503
504 while (*p) {
505 if (*p == target)
506 return target;
507
508 if ((best < target && *p > best) || (*p >= target &&
509 abs_diff(target, *p) < abs_diff(target, best)))
510 {
511 best = *p;
512 }
513
514 p += 1;
515 }
516
517 return best;
518 }
519
closest_supported_channel_layout(AVCodec * codec,uint64_t target)520 static uint64_t closest_supported_channel_layout(AVCodec *codec, uint64_t target) {
521 // if we can, return exact match. otherwise, return the layout with the
522 // minimum number of channels >= target
523
524 if (!codec->channel_layouts)
525 return target;
526
527 int target_count = av_get_channel_layout_nb_channels(target);
528 const uint64_t *p = codec->channel_layouts;
529 uint64_t best = *p;
530 int best_count = av_get_channel_layout_nb_channels(best);
531 while (*p) {
532 if (*p == target)
533 return target;
534
535 int count = av_get_channel_layout_nb_channels(*p);
536 if ((best_count < target_count && count > best_count) ||
537 (count >= target_count &&
538 abs_diff(target_count, count) < abs_diff(target_count, best_count)))
539 {
540 best_count = count;
541 best = *p;
542 }
543
544 p += 1;
545 }
546
547 return best;
548 }
549
log_audio_fmt(const struct GrooveAudioFormat * fmt)550 static void log_audio_fmt(const struct GrooveAudioFormat *fmt) {
551 char buf[128];
552
553 av_get_channel_layout_string(buf, sizeof(buf), 0, fmt->channel_layout);
554 av_log(NULL, AV_LOG_INFO, "encoder: using audio format: %s, %d Hz, %s\n",
555 av_get_sample_fmt_name((enum AVSampleFormat)fmt->sample_fmt),
556 fmt->sample_rate, buf);
557 }
558
groove_encoder_attach(struct GrooveEncoder * encoder,struct GroovePlaylist * playlist)559 int groove_encoder_attach(struct GrooveEncoder *encoder, struct GroovePlaylist *playlist) {
560 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
561
562 encoder->playlist = playlist;
563 groove_queue_reset(e->audioq);
564
565 e->oformat = av_guess_format(encoder->format_short_name,
566 encoder->filename, encoder->mime_type);
567 if (!e->oformat) {
568 groove_encoder_detach(encoder);
569 av_log(NULL, AV_LOG_ERROR, "unable to determine format\n");
570 return -1;
571 }
572
573 // av_guess_codec ignores mime_type, filename, and codec_short_name. see
574 // https://bugzilla.libav.org/show_bug.cgi?id=580
575 // because of this we do a workaround to return the correct codec based on
576 // the codec_short_name.
577 AVCodec *codec = NULL;
578 if (encoder->codec_short_name) {
579 codec = avcodec_find_encoder_by_name(encoder->codec_short_name);
580 if (!codec) {
581 const AVCodecDescriptor *desc =
582 avcodec_descriptor_get_by_name(encoder->codec_short_name);
583 if (desc) {
584 codec = avcodec_find_encoder(desc->id);
585 }
586 }
587 }
588 if (!codec) {
589 enum AVCodecID codec_id = av_guess_codec(e->oformat,
590 encoder->codec_short_name, encoder->filename, encoder->mime_type,
591 AVMEDIA_TYPE_AUDIO);
592 codec = avcodec_find_encoder(codec_id);
593 if (!codec) {
594 groove_encoder_detach(encoder);
595 av_log(NULL, AV_LOG_ERROR, "unable to find encoder\n");
596 return -1;
597 }
598 }
599 e->codec = codec;
600 av_log(NULL, AV_LOG_INFO, "encoder: using codec: %s\n", codec->long_name);
601
602 encoder->actual_audio_format.sample_fmt = closest_supported_sample_fmt(
603 codec, encoder->target_audio_format.sample_fmt);
604 encoder->actual_audio_format.sample_rate = closest_supported_sample_rate(
605 codec, encoder->target_audio_format.sample_rate);
606 encoder->actual_audio_format.channel_layout = closest_supported_channel_layout(
607 codec, encoder->target_audio_format.channel_layout);
608
609 log_audio_fmt(&encoder->actual_audio_format);
610
611 int err = init_avcontext(encoder);
612 if (err < 0) {
613 groove_encoder_detach(encoder);
614 return err;
615 }
616
617 e->sink->audio_format = encoder->actual_audio_format;
618 e->sink->buffer_size = encoder->sink_buffer_size;
619 e->sink->buffer_sample_count = (codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ?
620 0 : e->stream->codec->frame_size;
621 e->sink->gain = encoder->gain;
622
623 if (groove_sink_attach(e->sink, playlist) < 0) {
624 groove_encoder_detach(encoder);
625 av_log(NULL, AV_LOG_ERROR, "unable to attach sink\n");
626 return -1;
627 }
628
629 if (pthread_create(&e->thread_id, NULL, encode_thread, encoder) != 0) {
630 groove_encoder_detach(encoder);
631 av_log(NULL, AV_LOG_ERROR, "unable to create encoder thread\n");
632 return -1;
633 }
634
635 return 0;
636 }
637
groove_encoder_detach(struct GrooveEncoder * encoder)638 int groove_encoder_detach(struct GrooveEncoder *encoder) {
639 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
640
641 e->abort_request = 1;
642 groove_sink_detach(e->sink);
643 groove_queue_flush(e->audioq);
644 groove_queue_abort(e->audioq);
645 pthread_cond_signal(&e->drain_cond);
646 pthread_join(e->thread_id, NULL);
647 e->abort_request = 0;
648
649 cleanup_avcontext(e);
650 e->oformat = NULL;
651 e->codec = NULL;
652
653 encoder->playlist = NULL;
654 return 0;
655 }
656
groove_encoder_buffer_get(struct GrooveEncoder * encoder,struct GrooveBuffer ** buffer,int block)657 int groove_encoder_buffer_get(struct GrooveEncoder *encoder,
658 struct GrooveBuffer **buffer, int block)
659 {
660 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
661
662 if (groove_queue_get(e->audioq, (void**)buffer, block) == 1) {
663 if (*buffer == end_of_q_sentinel) {
664 *buffer = NULL;
665 return GROOVE_BUFFER_END;
666 } else {
667 return GROOVE_BUFFER_YES;
668 }
669 } else {
670 *buffer = NULL;
671 return GROOVE_BUFFER_NO;
672 }
673 }
674
groove_encoder_metadata_get(struct GrooveEncoder * encoder,const char * key,const struct GrooveTag * prev,int flags)675 struct GrooveTag *groove_encoder_metadata_get(struct GrooveEncoder *encoder, const char *key,
676 const struct GrooveTag *prev, int flags)
677 {
678 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
679 const AVDictionaryEntry *entry = (const AVDictionaryEntry *) prev;
680 return (struct GrooveTag *) av_dict_get(e->metadata, key, entry, flags|AV_DICT_IGNORE_SUFFIX);
681 }
682
groove_encoder_metadata_set(struct GrooveEncoder * encoder,const char * key,const char * value,int flags)683 int groove_encoder_metadata_set(struct GrooveEncoder *encoder, const char *key,
684 const char *value, int flags)
685 {
686 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
687 return av_dict_set(&e->metadata, key, value, flags|AV_DICT_IGNORE_SUFFIX);
688 }
689
groove_encoder_buffer_peek(struct GrooveEncoder * encoder,int block)690 int groove_encoder_buffer_peek(struct GrooveEncoder *encoder, int block) {
691 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
692 return groove_queue_peek(e->audioq, block);
693 }
694
groove_encoder_position(struct GrooveEncoder * encoder,struct GroovePlaylistItem ** item,double * seconds)695 void groove_encoder_position(struct GrooveEncoder *encoder,
696 struct GroovePlaylistItem **item, double *seconds)
697 {
698 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
699
700 pthread_mutex_lock(&e->encode_head_mutex);
701
702 if (item)
703 *item = e->encode_head;
704
705 if (seconds)
706 *seconds = e->encode_pos;
707
708 pthread_mutex_unlock(&e->encode_head_mutex);
709 }
710
groove_encoder_set_gain(struct GrooveEncoder * encoder,double gain)711 int groove_encoder_set_gain(struct GrooveEncoder *encoder, double gain) {
712 struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
713 encoder->gain = gain;
714 return groove_sink_set_gain(e->sink, gain);
715 }
716