On 06.11.2014 01:32, Michael Niedermayer wrote:
On Thu, Nov 06, 2014 at 12:59:45AM +0100, Lukasz Marek wrote:
new_output_stream creates a codec context with arbitraty picked codec.
Later data is updated, but priv_data are left alone.
There is a bit chance there is a mismatch between codecs.

Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com>
---
  ffmpeg_opt.c         | 16 ++++++++++++++++
  libavformat/ffmdec.c |  6 ++++--
  2 files changed, 20 insertions(+), 2 deletions(-)

with this fate-lavf-ffm crashes

==10836== Invalid write of size 8
==10836==    at 0x935442: decode_init (mpegaudiodec_template.c:419)
==10836==    by 0xA69226: avcodec_open2 (utils.c:1614)
==10836==    by 0x64CC5F: avformat_find_stream_info (utils.c:3053)
==10836==    by 0x41C2D7: open_input_file (ffmpeg_opt.c:886)
==10836==    by 0x42427A: open_files (ffmpeg_opt.c:2699)
==10836==    by 0x4243F8: ffmpeg_parse_options (ffmpeg_opt.c:2736)
==10836==    by 0x43762E: main (ffmpeg.c:3861)
==10836==  Address 0x10f072b0 is not stack'd, malloc'd or (recently) free'd
==10836==
==10836== Invalid write of size 8
==10836==    at 0xDC67D0: avpriv_float_dsp_init (float_dsp.c:120)
==10836==    by 0x93546B: decode_init (mpegaudiodec_template.c:421)
==10836==    by 0xA69226: avcodec_open2 (utils.c:1614)
==10836==    by 0x64CC5F: avformat_find_stream_info (utils.c:3053)
==10836==    by 0x41C2D7: open_input_file (ffmpeg_opt.c:886)
==10836==    by 0x42427A: open_files (ffmpeg_opt.c:2699)
==10836==    by 0x4243F8: ffmpeg_parse_options (ffmpeg_opt.c:2736)
==10836==    by 0x43762E: main (ffmpeg.c:3861)
==10836==  Address 0x10f072e8 is not stack'd, malloc'd or (recently) free'd
and pages more

I tried to debug it, but there is too much code to read to handle one very specific case and I'm not sure there is other, better solution. Probably, I haven't check, clear solution would be to clear priv_data in read_ffserver_streams right after copy_context, and set it to NULL, but I will need private data soon to support it in ffserver.

Solution is ugly, but I think I will not propose anything better.

>From abb6a1fb9c1da226b6bfe179ded076365b969cad Mon Sep 17 00:00:00 2001
From: Lukasz Marek <lukasz.m.lu...@gmail.com>
Date: Thu, 6 Nov 2014 00:55:10 +0100
Subject: [PATCH] ffmpeg_opt: set correct priv_data for feed stream

new_output_stream creates a codec context with arbitraty picked codec.
Later data is updated, but priv_data are left alone.
There is a bit chance there is a mismatch between codecs.

Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com>
---
 ffmpeg_opt.c         | 20 +++++++++++++++++++-
 libavformat/ffm.h    |  3 +++
 libavformat/ffmdec.c | 28 ++++++++++++++++++++++++----
 3 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index 1757dcc..d020c13 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -1614,9 +1614,11 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
 {
     int i, err;
     AVFormatContext *ic = avformat_alloc_context();
+    AVDictionary *opts = NULL;
 
     ic->interrupt_callback = int_cb;
-    err = avformat_open_input(&ic, filename, NULL, NULL);
+    av_dict_set_int(&opts, "need_stream", 1500100900, 0);
+    err = avformat_open_input(&ic, filename, NULL, &opts);
     if (err < 0)
         return err;
     /* copy stream format */
@@ -1643,12 +1645,28 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
         memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
         st->codec= avctx;
         avcodec_copy_context(st->codec, ic->streams[i]->codec);
+        if (st->codec->priv_data) {
+            av_opt_free(st->codec->priv_data);
+            av_free(st->codec->priv_data);
+        }
+        st->codec->priv_data = ic->streams[i]->codec->priv_data;
+        ic->streams[i]->codec->priv_data = NULL;
 
         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_free(ost->enc_ctx->priv_data);
+        }
+        ost->enc_ctx->priv_data = av_mallocz(codec->priv_data_size);
+        if (ost->enc_ctx->priv_data) {
+            *(const AVClass**)ost->enc_ctx->priv_data = codec->priv_class;
+            av_opt_copy(ost->enc_ctx->priv_data, st->codec->priv_data);
+        } else
+            err = AVERROR(ENOMEM);
     }
 
     avformat_close_input(&ic);
diff --git a/libavformat/ffm.h b/libavformat/ffm.h
index b392b8d..0ab92f1 100644
--- a/libavformat/ffm.h
+++ b/libavformat/ffm.h
@@ -43,6 +43,9 @@ enum {
 
 typedef struct FFMContext {
     /* only reading mode */
+    AVClass *avclass;
+    int need_streams;
+
     int64_t write_index, file_size;
     int read_state;
     uint8_t header[FRAME_HEADER_SIZE+4];
diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index 448762b..e34431c 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -23,6 +23,7 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/intfloat.h"
+#include "libavutil/opt.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -237,6 +238,7 @@ static int ffm2_read_header(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AVCodecContext *codec;
     int ret;
+    enum AVCodecID codec_id;
 
     ffm->packet_size = avio_rb32(pb);
     if (ffm->packet_size != FFM_PACKET_SIZE) {
@@ -271,7 +273,8 @@ static int ffm2_read_header(AVFormatContext *s)
             avio_rb32(pb); /* total bitrate */
             break;
         case MKBETAG('C', 'O', 'M', 'M'):
-            st = avformat_new_stream(s, NULL);
+            codec_id = avio_rb32(pb);
+            st = avformat_new_stream(s, ffm->need_streams == 1500100900 ? avcodec_find_encoder(codec_id) : NULL);
             if (!st) {
                 ret = AVERROR(ENOMEM);
                 goto fail;
@@ -281,7 +284,7 @@ static int ffm2_read_header(AVFormatContext *s)
 
             codec = st->codec;
             /* generic info */
-            codec->codec_id = avio_rb32(pb);
+            codec->codec_id = codec_id;
             codec->codec_type = avio_r8(pb);
             codec->bit_rate = avio_rb32(pb);
             codec->flags = avio_rb32(pb);
@@ -378,6 +381,7 @@ static int ffm_read_header(AVFormatContext *s)
     AVCodecContext *codec;
     int i, nb_streams;
     uint32_t tag;
+    enum AVCodecID codec_id;
 
     /* header */
     tag = avio_rl32(pb);
@@ -404,7 +408,8 @@ static int ffm_read_header(AVFormatContext *s)
     for(i=0;i<nb_streams;i++) {
         char rc_eq_buf[128];
 
-        st = avformat_new_stream(s, NULL);
+        codec_id = avio_rb32(pb);
+        st = avformat_new_stream(s, ffm->need_streams == 1500100900 ? avcodec_find_encoder(codec_id) : NULL);
         if (!st)
             goto fail;
 
@@ -412,7 +417,7 @@ static int ffm_read_header(AVFormatContext *s)
 
         codec = st->codec;
         /* generic info */
-        codec->codec_id = avio_rb32(pb);
+        codec->codec_id = codec_id;
         codec->codec_type = avio_r8(pb); /* codec_type */
         codec->bit_rate = avio_rb32(pb);
         codec->flags = avio_rb32(pb);
@@ -631,8 +636,23 @@ static int ffm_probe(AVProbeData *p)
     return 0;
 }
 
+#define OFFSET(x) offsetof(FFMContext, x)
+#define ENC AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "need_stream", "FFServer hack option, not to used by user", OFFSET(need_streams), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, ENC },
+    { NULL },
+};
+
+static const AVClass ffm_demuxer_class = {
+    .class_name = "FFM demuxer",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+    .option     = options,
+};
+
 AVInputFormat ff_ffm_demuxer = {
     .name           = "ffm",
+    .priv_class     = &ffm_demuxer_class,
     .long_name      = NULL_IF_CONFIG_SMALL("FFM (FFserver live feed)"),
     .priv_data_size = sizeof(FFMContext),
     .read_probe     = ffm_probe,
-- 
1.9.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to