]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/flvenc.c
avformat/flvenc: flx flvflags no_metadata bug
[ffmpeg] / libavformat / flvenc.c
index 4ca6aea9f7efe84e617fe50f8deb4707dbf859d9..899b07ea7bef8575347c757e7a3de1459ef5437b 100644 (file)
@@ -67,6 +67,8 @@ typedef enum {
     FLV_AAC_SEQ_HEADER_DETECT = (1 << 0),
     FLV_NO_SEQUENCE_END = (1 << 1),
     FLV_ADD_KEYFRAME_INDEX = (1 << 2),
+    FLV_NO_METADATA = (1 << 3),
+    FLV_NO_DURATION_FILESIZE = (1 << 4),
 } FLVFlags;
 
 typedef struct FLVFileposition {
@@ -268,6 +270,7 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
 {
     AVIOContext *pb = s->pb;
     FLVContext *flv = s->priv_data;
+    int write_duration_filesize = !(flv->flags & FLV_NO_DURATION_FILESIZE);
     int metadata_count = 0;
     int64_t metadata_count_pos;
     AVDictionaryEntry *tag = NULL;
@@ -291,12 +294,12 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
     metadata_count = 4 * !!flv->video_par +
                      5 * !!flv->audio_par +
                      1 * !!flv->data_par;
-    if (pb->seekable) {
+    if (write_duration_filesize) {
         metadata_count += 2; // +2 for duration and file size
     }
     avio_wb32(pb, metadata_count);
 
-    if (pb->seekable) {
+    if (write_duration_filesize) {
         put_amf_string(pb, "duration");
         flv->duration_offset = avio_tell(pb);
         // fill in the guessed duration, it'll be corrected later if incorrect
@@ -377,7 +380,7 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
         metadata_count++;
     }
 
-    if (pb->seekable) {
+    if (write_duration_filesize) {
         put_amf_string(pb, "filesize");
         flv->filesize_offset = avio_tell(pb);
         put_amf_double(pb, 0); // delayed write
@@ -623,13 +626,15 @@ static int shift_data(AVFormatContext *s)
     avio_seek(read_pb, flv->keyframes_info_offset, SEEK_SET);
     pos = avio_tell(read_pb);
 
-    /* shift data by chunk of at most keyframe *filepositions* and *times* size */
+#define READ_BLOCK do {                                                             \
     read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size);  \
-    read_buf_id ^= 1;
-    do {
+    read_buf_id ^= 1;                                                               \
+} while (0)
 
-        read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size);  \
-        read_buf_id ^= 1;
+    /* shift data by chunk of at most keyframe *filepositions* and *times* size */
+    READ_BLOCK;
+    do {
+        READ_BLOCK;
         n = read_size[read_buf_id];
         if (n < 0)
             break;
@@ -744,7 +749,11 @@ static int flv_write_header(AVFormatContext *s)
             flv->reserved = 5;
         }
 
-    write_metadata(s, 0);
+    if (flv->flags & FLV_NO_METADATA) {
+        pb->seekable = 0;
+    } else {
+        write_metadata(s, 0);
+    }
 
     for (i = 0; i < s->nb_streams; i++) {
         flv_write_codec_header(s, s->streams[i]->codecpar);
@@ -839,20 +848,22 @@ end:
         avio_seek(pb, flv->datasize_offset, SEEK_SET);
         put_amf_double(pb, flv->datasize);
     }
-    if (pb->seekable) {
-        /* update information */
-        if (avio_seek(pb, flv->duration_offset, SEEK_SET) < 0) {
-            av_log(s, AV_LOG_WARNING, "Failed to update header with correct duration.\n");
-        } else {
-            put_amf_double(pb, flv->duration / (double)1000);
-        }
-        if (avio_seek(pb, flv->filesize_offset, SEEK_SET) < 0) {
-            av_log(s, AV_LOG_WARNING, "Failed to update header with correct filesize.\n");
-        } else {
-            put_amf_double(pb, file_size);
+    if (!(flv->flags & FLV_NO_METADATA)) {
+        if (!(flv->flags & FLV_NO_DURATION_FILESIZE)) {
+            /* update information */
+            if (avio_seek(pb, flv->duration_offset, SEEK_SET) < 0) {
+                av_log(s, AV_LOG_WARNING, "Failed to update header with correct duration.\n");
+            } else {
+                put_amf_double(pb, flv->duration / (double)1000);
+            }
+            if (avio_seek(pb, flv->filesize_offset, SEEK_SET) < 0) {
+                av_log(s, AV_LOG_WARNING, "Failed to update header with correct filesize.\n");
+            } else {
+                put_amf_double(pb, file_size);
+            }
         }
     }
-    avio_seek(pb, file_size, SEEK_SET);
+
     return 0;
 }
 
@@ -883,6 +894,10 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
         if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
             av_free(par->extradata);
             par->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!par->extradata) {
+                par->extradata_size = 0;
+                return AVERROR(ENOMEM);
+            }
             memcpy(par->extradata, side, side_size);
             par->extradata_size = side_size;
             flv_write_codec_header(s, par);
@@ -1055,6 +1070,8 @@ static const AVOption options[] = {
     { "flvflags", "FLV muxer flags", offsetof(FLVContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
     { "aac_seq_header_detect", "Put AAC sequence header based on stream data", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_AAC_SEQ_HEADER_DETECT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
     { "no_sequence_end", "disable sequence end for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_SEQUENCE_END}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
+    { "no_metadata", "disable metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_METADATA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
+    { "no_duration_filesize", "disable duration and filesize zero value metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_DURATION_FILESIZE}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
     { "add_keyframe_index", "Add keyframe index metadata", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_ADD_KEYFRAME_INDEX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
     { NULL },
 };