ffmpeg_opt: use codec private context in ffserver streams
authorLukasz Marek <lukasz.m.luki2@gmail.com>
Tue, 11 Nov 2014 04:19:27 +0000 (05:19 +0100)
committerLukasz Marek <lukasz.m.luki2@gmail.com>
Sun, 16 Nov 2014 00:13:38 +0000 (01:13 +0100)
Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
ffmpeg_opt.c

index 77ef0c4..85466c7 100644 (file)
@@ -1617,6 +1617,31 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
     return 0;
 }
 
+static int ffserver_streams_copy_context(AVCodecContext *dest, const AVCodecContext *src,
+                                         const char *configuration)
+{
+    int ret;
+    if ((ret = avcodec_copy_context(dest, src)) < 0)
+        return ret;
+    dest->codec = avcodec_find_encoder(src->codec_id);
+    if (!dest->codec)
+        return AVERROR(EINVAL);
+    if (!dest->codec->priv_class || !dest->codec->priv_data_size)
+        return 0;
+    if (!dest->priv_data) {
+        dest->priv_data = av_mallocz(dest->codec->priv_data_size);
+        if (!dest->priv_data)
+            return AVERROR(ENOMEM);
+        *(const AVClass**)dest->priv_data = dest->codec->priv_class;
+    }
+    av_opt_set_defaults(dest->priv_data);
+    if (av_set_options_string(dest->priv_data, configuration, "=", ",") < 0) {
+        av_log(dest, AV_LOG_WARNING, "Cannot copy private codec options. Using defaults.\n");
+        av_opt_set_defaults(dest->priv_data);
+    }
+    return 0;
+}
+
 static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
 {
     int i, err;
@@ -1631,35 +1656,28 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
         AVStream *st;
         OutputStream *ost;
         AVCodec *codec;
-        AVCodecContext *avctx;
 
         codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
         if (!codec) {
             av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codec->codec_id);
             return AVERROR(EINVAL);
         }
+        if (codec->type == AVMEDIA_TYPE_AUDIO)
+            opt_audio_codec(o, "c:a", codec->name);
+        else if (codec->type == AVMEDIA_TYPE_VIDEO)
+            opt_video_codec(o, "c:v", codec->name);
         ost   = new_output_stream(o, s, codec->type, -1);
         st    = ost->st;
-        avctx = st->codec;
-        ost->enc = codec;
 
-        // FIXME: a more elegant solution is needed
-        memcpy(st, ic->streams[i], sizeof(AVStream));
-        st->cur_dts = 0;
-        st->info = av_malloc(sizeof(*st->info));
-        memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
-        st->codec= avctx;
-        avcodec_copy_context(st->codec, ic->streams[i]->codec);
+        ffserver_streams_copy_context(st->codec, ic->streams[i]->codec,
+                                      av_stream_get_recommended_encoder_configuration(ic->streams[i]));
 
         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
             choose_sample_fmt(st, codec);
         else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
             choose_pixel_fmt(st, st->codec, codec, st->codec->pix_fmt);
-        avcodec_copy_context(ost->enc_ctx, st->codec);
-        if (ost->enc_ctx->priv_data) {
-            av_opt_free(ost->enc_ctx->priv_data);
-            av_freep(&ost->enc_ctx->priv_data);
-        }
+        ffserver_streams_copy_context(ost->enc_ctx, st->codec,
+                                      av_stream_get_recommended_encoder_configuration(ic->streams[i]));
     }
 
     avformat_close_input(&ic);