[SCM] libgroove/upstream: encoder: create new AVFormatContext on flush and playlist end

andrewrk-guest at users.alioth.debian.org andrewrk-guest at users.alioth.debian.org
Sat May 31 19:00:02 UTC 2014


The following commit has been merged in the upstream branch:
commit 2df706dd937f675bb9d7f9856d75aefbadee7170
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Sat May 31 11:43:55 2014 -0700

    encoder: create new AVFormatContext on flush and playlist end
    
    Closes #66

diff --git a/groove/encoder.c b/groove/encoder.c
index 948279e..42a55bd 100644
--- a/groove/encoder.c
+++ b/groove/encoder.c
@@ -24,6 +24,8 @@ struct GrooveEncoderPrivate {
     struct GrooveQueue *audioq;
     struct GrooveSink *sink;
     AVFormatContext *fmt_ctx;
+    AVOutputFormat *oformat;
+    AVCodec *codec;
     AVStream *stream;
     AVPacket pkt;
     int audioq_size; // in bytes
@@ -94,6 +96,60 @@ static int encode_buffer(struct GrooveEncoder *encoder, struct GrooveBuffer *buf
     return 0;
 }
 
+static void cleanup_avcontext(struct GrooveEncoderPrivate *e) {
+    if (e->stream) {
+        avcodec_close(e->stream->codec);
+        // stream is freed by freeing the AVFormatContext
+        e->stream = NULL;
+    }
+
+    if (e->fmt_ctx) {
+        avformat_free_context(e->fmt_ctx);
+        e->fmt_ctx = NULL;
+    }
+
+    e->sent_header = 0;
+    e->encode_head = NULL;
+    e->encode_pos = -1.0;
+    e->encode_pts = 0;
+    e->next_pts = 0;
+}
+
+static int init_avcontext(struct GrooveEncoder *encoder) {
+    struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
+    e->fmt_ctx = avformat_alloc_context();
+    if (!e->fmt_ctx) {
+        av_log(NULL, AV_LOG_ERROR, "unable to allocate format context\n");
+        return -1;
+    }
+    e->fmt_ctx->pb = e->avio;
+    e->fmt_ctx->oformat = e->oformat;
+
+    e->stream = avformat_new_stream(e->fmt_ctx, e->codec);
+    if (!e->stream) {
+        av_log(NULL, AV_LOG_ERROR, "unable to create output stream\n");
+        return -1;
+    }
+
+    AVCodecContext *codec_ctx = e->stream->codec;
+    codec_ctx->bit_rate = encoder->bit_rate;
+    codec_ctx->sample_fmt = (enum AVSampleFormat)encoder->actual_audio_format.sample_fmt;
+    codec_ctx->sample_rate = encoder->actual_audio_format.sample_rate;
+    codec_ctx->channel_layout = encoder->actual_audio_format.channel_layout;
+    codec_ctx->channels = av_get_channel_layout_nb_channels(encoder->actual_audio_format.channel_layout);
+    codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+
+    int err = avcodec_open2(codec_ctx, e->codec, NULL);
+    if (err < 0) {
+        av_strerror(err, e->strbuf, sizeof(e->strbuf));
+        av_log(NULL, AV_LOG_ERROR, "unable to open codec: %s\n", e->strbuf);
+        return -1;
+    }
+    e->stream->codec = codec_ctx;
+
+    return 0;
+}
+
 static void *encode_thread(void *arg) {
     struct GrooveEncoder *encoder = arg;
     struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
@@ -125,9 +181,6 @@ static void *encode_thread(void *arg) {
 
             // send trailer
             avio_flush(e->avio);
-            e->sent_header = 0;
-            e->encode_head = NULL;
-            e->encode_pos = -1.0;
             av_log(NULL, AV_LOG_INFO, "encoder: writing trailer\n");
             if (av_write_trailer(e->fmt_ctx) < 0) {
                 av_log(NULL, AV_LOG_ERROR, "could not write trailer\n");
@@ -136,6 +189,9 @@ static void *encode_thread(void *arg) {
 
             groove_queue_put(e->audioq, end_of_q_sentinel);
 
+            cleanup_avcontext(e);
+            init_avcontext(encoder);
+
             pthread_mutex_unlock(&e->encode_head_mutex);
             continue;
         }
@@ -188,11 +244,16 @@ static void sink_purge(struct GrooveSink *sink, struct GroovePlaylistItem *item)
 }
 
 static void sink_flush(struct GrooveSink *sink) {
-    struct GrooveEncoderPrivate *e = sink->userdata;
+    struct GrooveEncoder *encoder = sink->userdata;
+    struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder;
 
     pthread_mutex_lock(&e->encode_head_mutex);
     groove_queue_flush(e->audioq);
-    avcodec_flush_buffers(e->stream->codec);
+
+    cleanup_avcontext(e);
+    init_avcontext(encoder);
+    groove_queue_put(e->audioq, end_of_q_sentinel);
+
     pthread_cond_signal(&e->drain_cond);
     pthread_mutex_unlock(&e->encode_head_mutex);
 }
@@ -501,21 +562,14 @@ int groove_encoder_attach(struct GrooveEncoder *encoder, struct GroovePlaylist *
     encoder->playlist = playlist;
     groove_queue_reset(e->audioq);
 
-    e->fmt_ctx = avformat_alloc_context();
-    if (!e->fmt_ctx) {
-        groove_encoder_detach(encoder);
-        av_log(NULL, AV_LOG_ERROR, "unable to allocate format context\n");
-        return -1;
-    }
-    e->fmt_ctx->pb = e->avio;
-
-    e->fmt_ctx->oformat = av_guess_format(encoder->format_short_name,
+    e->oformat = av_guess_format(encoder->format_short_name,
             encoder->filename, encoder->mime_type);
-    if (!e->fmt_ctx->oformat) {
+    if (!e->oformat) {
         groove_encoder_detach(encoder);
         av_log(NULL, AV_LOG_ERROR, "unable to determine format\n");
         return -1;
     }
+
     // av_guess_codec ignores mime_type, filename, and codec_short_name. see
     // https://bugzilla.libav.org/show_bug.cgi?id=580
     // because of this we do a workaround to return the correct codec based on
@@ -532,7 +586,7 @@ int groove_encoder_attach(struct GrooveEncoder *encoder, struct GroovePlaylist *
         }
     }
     if (!codec) {
-        enum AVCodecID codec_id = av_guess_codec(e->fmt_ctx->oformat,
+        enum AVCodecID codec_id = av_guess_codec(e->oformat,
                 encoder->codec_short_name, encoder->filename, encoder->mime_type,
                 AVMEDIA_TYPE_AUDIO);
         codec = avcodec_find_encoder(codec_id);
@@ -542,15 +596,9 @@ int groove_encoder_attach(struct GrooveEncoder *encoder, struct GroovePlaylist *
             return -1;
         }
     }
+    e->codec = codec;
     av_log(NULL, AV_LOG_INFO, "encoder: using codec: %s\n", codec->long_name);
 
-    e->stream = avformat_new_stream(e->fmt_ctx, codec);
-    if (!e->stream) {
-        groove_encoder_detach(encoder);
-        av_log(NULL, AV_LOG_ERROR, "unable to create output stream\n");
-        return -1;
-    }
-
     encoder->actual_audio_format.sample_fmt = closest_supported_sample_fmt(
             codec, encoder->target_audio_format.sample_fmt);
     encoder->actual_audio_format.sample_rate = closest_supported_sample_rate(
@@ -560,28 +608,16 @@ int groove_encoder_attach(struct GrooveEncoder *encoder, struct GroovePlaylist *
 
     log_audio_fmt(&encoder->actual_audio_format);
 
-    AVCodecContext *codec_ctx = e->stream->codec;
-    codec_ctx->bit_rate = encoder->bit_rate;
-    codec_ctx->sample_fmt = (enum AVSampleFormat)encoder->actual_audio_format.sample_fmt;
-    codec_ctx->sample_rate = encoder->actual_audio_format.sample_rate;
-    codec_ctx->channel_layout = encoder->actual_audio_format.channel_layout;
-    codec_ctx->channels = av_get_channel_layout_nb_channels(encoder->actual_audio_format.channel_layout);
-    codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
-
-    e->stream->codec = codec_ctx;
-
-    int errcode = avcodec_open2(codec_ctx, codec, NULL);
-    if (errcode < 0) {
+    int err = init_avcontext(encoder);
+    if (err < 0) {
         groove_encoder_detach(encoder);
-        av_strerror(errcode, e->strbuf, sizeof(e->strbuf));
-        av_log(NULL, AV_LOG_ERROR, "unable to open codec: %s\n", e->strbuf);
-        return -1;
+        return err;
     }
 
     e->sink->audio_format = encoder->actual_audio_format;
     e->sink->buffer_size = encoder->sink_buffer_size;
     e->sink->buffer_sample_count = (codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) ?
-        0 : codec_ctx->frame_size;
+        0 : e->stream->codec->frame_size;
     e->sink->gain = encoder->gain;
 
     if (groove_sink_attach(e->sink, playlist) < 0) {
@@ -608,22 +644,11 @@ int groove_encoder_detach(struct GrooveEncoder *encoder) {
     groove_queue_abort(e->audioq);
     pthread_cond_signal(&e->drain_cond);
     pthread_join(e->thread_id, NULL);
-
-    if (e->stream) {
-        avcodec_close(e->stream->codec);
-        // stream is freed by freeing the AVFormatContext
-        e->stream = NULL;
-    }
-
-    if (e->fmt_ctx)
-        avformat_free_context(e->fmt_ctx);
-
-    e->encode_head = NULL;
-    e->encode_pos = -1.0;
-    e->encode_pts = 0;
-    e->sent_header = 0;
     e->abort_request = 0;
-    e->next_pts = 0;
+
+    cleanup_avcontext(e);
+    e->oformat = NULL;
+    e->codec = NULL;
 
     encoder->playlist = NULL;
     return 0;

-- 
libgroove packaging



More information about the pkg-multimedia-commits mailing list