]> git.sesse.net Git - ffmpeg/commitdiff
support changing in bitstream global headers into extradata style and back
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 27 Jun 2005 00:04:03 +0000 (00:04 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 27 Jun 2005 00:04:03 +0000 (00:04 +0000)
Originally committed as revision 4395 to svn://svn.ffmpeg.org/ffmpeg/trunk

ffmpeg.c
libavcodec/avcodec.h
libavcodec/parser.c
libavformat/avformat.h
libavformat/utils.c

index 10ecfaccacc3b5a6bc4131da78d8a9c7fb578347..dfa38a13b6ea2e2f43d3e6dd0ff9aba6505e8820 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -254,6 +254,7 @@ static int video_sync_method= 1;
 static int audio_sync_method= 0;
 static int copy_ts= 0;
 static int opt_shortest = 0; //
+static int video_global_header = 0;
 
 static int rate_emu = 0;
 
@@ -1396,8 +1397,6 @@ static int output_packet(AVInputStream *ist, int ist_index,
                             }
 
                             opkt.stream_index= ost->index;
-                            opkt.data= data_buf;
-                            opkt.size= data_size;
                             if(pkt->pts != AV_NOPTS_VALUE)
                                 opkt.pts= av_rescale_q(av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q,  ost->st->time_base);
                             else
@@ -1412,9 +1411,12 @@ static int output_packet(AVInputStream *ist, int ist_index,
                                 opkt.dts= av_rescale_q(dts + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q,  ost->st->time_base);
                             }
                             opkt.flags= pkt->flags;
+                            if(av_parser_change(ist->st->parser, &ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY))
+                                opkt.destruct= av_destruct_packet;
                             av_interleaved_write_frame(os, &opkt);
                             ost->st->codec.frame_number++;
                             ost->frame_number++;
+                            av_free_packet(&opkt);
                         }
                     }
                 }
@@ -3187,8 +3189,12 @@ static void new_video_stream(AVFormatContext *oc)
     if(video_codec_tag)
         video_enc->codec_tag= video_codec_tag;
     
-    if (oc->oformat->flags & AVFMT_GLOBALHEADER) 
+    if(   (video_global_header&1)
+       || (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER)))
         video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
+    if(video_global_header&2)
+        video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
+
     if (video_stream_copy) {
         st->stream_copy = 1;
         video_enc->codec_type = CODEC_TYPE_VIDEO;
@@ -4189,6 +4195,7 @@ const OptionDef options[] = {
     { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
     { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
     { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
+    { "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_global_header}, "video global header storage type", "" },
     { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" },
     { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
 
index 3ab04e0086fdb2f9a051503c8ea46a3b326f9325..6f644f64935bfd9d71fd0692abc36be26b2a7d60 100644 (file)
@@ -341,6 +341,7 @@ extern int motion_estimation_method;
 #define CODEC_FLAG2_FAST          0x00000001 ///< allow non spec compliant speedup tricks
 #define CODEC_FLAG2_STRICT_GOP    0x00000002 ///< strictly enforce GOP size
 #define CODEC_FLAG2_NO_OUTPUT     0x00000004 ///< skip bitstream encoding
+#define CODEC_FLAG2_LOCAL_HEADER  0x00000008 ///< place global headers at every keyframe instead of in extradata
 
 /* Unsupported options :
  *             Syntax Arithmetic coding (SAC)
@@ -2322,6 +2323,7 @@ typedef struct AVCodecParser {
                         uint8_t **poutbuf, int *poutbuf_size, 
                         const uint8_t *buf, int buf_size);
     void (*parser_close)(AVCodecParserContext *s);
+    int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
     struct AVCodecParser *next;
 } AVCodecParser;
 
@@ -2334,6 +2336,10 @@ int av_parser_parse(AVCodecParserContext *s,
                     uint8_t **poutbuf, int *poutbuf_size, 
                     const uint8_t *buf, int buf_size,
                     int64_t pts, int64_t dts);
+int av_parser_change(AVCodecParserContext *s,
+                     AVCodecContext *avctx,
+                     uint8_t **poutbuf, int *poutbuf_size, 
+                     const uint8_t *buf, int buf_size, int keyframe);
 void av_parser_close(AVCodecParserContext *s);
 
 extern AVCodecParser mpegvideo_parser;
index 93bbf87d1046b24d81e3ac2d19bd59a954e2b36a..88c57096d4fc5126a2f922b779730447112eb19b 100644 (file)
@@ -142,6 +142,38 @@ int av_parser_parse(AVCodecParserContext *s,
     return index;
 }
 
+int av_parser_change(AVCodecParserContext *s,
+                     AVCodecContext *avctx,
+                     uint8_t **poutbuf, int *poutbuf_size, 
+                     const uint8_t *buf, int buf_size, int keyframe){
+   
+    if(s && s->parser->split){
+        if((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) && !(avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)){
+            int i= s->parser->split(avctx, buf, buf_size);
+            buf += i;
+            buf_size -= i;
+        }
+    }
+
+    *poutbuf= buf;
+    *poutbuf_size= buf_size;
+    if(avctx->extradata){
+        if(  (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER))
+            /*||(s->pict_type != I_TYPE && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_NOKEY))*/
+            /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){
+            int size= buf_size + avctx->extradata_size;
+            *poutbuf_size= size;
+            *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+            
+            memcpy(*poutbuf, avctx->extradata, avctx->extradata_size);
+            memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size);
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
 void av_parser_close(AVCodecParserContext *s)
 {
     if (s->parser->parser_close)
@@ -294,7 +326,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s,
     int frame_rate_ext_n, frame_rate_ext_d;
     int picture_structure, top_field_first, repeat_first_field, progressive_frame;
     int horiz_size_ext, vert_size_ext, bit_rate_ext;
-
+//FIXME replace the crap with get_bits()
     s->repeat_pict = 0;
     buf_end = buf + buf_size;
     while (buf < buf_end) {
@@ -415,6 +447,20 @@ static int mpegvideo_parse(AVCodecParserContext *s,
     return next;
 }
 
+static int mpegvideo_split(AVCodecContext *avctx,
+                           const uint8_t *buf, int buf_size)
+{
+    int i;
+    uint32_t state= -1;
+    
+    for(i=0; i<buf_size; i++){
+        state= (state<<8) | buf[i];
+        if(state != 0x1B3 && state != 0x1B5 && state < 0x200 && state >= 0x100)
+            return i-4;
+    }
+    return 0;
+}
+
 void ff_parse_close(AVCodecParserContext *s)
 {
     ParseContext *pc = s->priv_data;
@@ -493,6 +539,20 @@ static int mpeg4video_parse(AVCodecParserContext *s,
     return next;
 }
 
+static int mpeg4video_split(AVCodecContext *avctx,
+                           const uint8_t *buf, int buf_size)
+{
+    int i;
+    uint32_t state= -1;
+    
+    for(i=0; i<buf_size; i++){
+        state= (state<<8) | buf[i];
+        if(state == 0x1B3 || state == 0x1B6)
+            return i-4;
+    }
+    return 0;
+}
+
 /*************************/
 
 typedef struct MpegAudioParseContext {
@@ -768,6 +828,7 @@ AVCodecParser mpegvideo_parser = {
     NULL,
     mpegvideo_parse,
     parse1_close,
+    mpegvideo_split,
 };
 
 AVCodecParser mpeg4video_parser = {
@@ -776,6 +837,7 @@ AVCodecParser mpeg4video_parser = {
     mpeg4video_parse_init,
     mpeg4video_parse,
     parse1_close,
+    mpeg4video_split,
 };
 
 AVCodecParser mpegaudio_parser = {
index c48386e7eea3fd61ac5a1ea9f23c79bf6893af55..0473595ac3e36474f67c8bc1875b1aa521f5d06a 100644 (file)
@@ -42,6 +42,7 @@ typedef struct AVPacket {
 #define PKT_FLAG_KEY   0x0001
 
 void av_destruct_packet_nofree(AVPacket *pkt);
+void av_destruct_packet(AVPacket *pkt);
 
 /* initialize optional fields of a packet */
 static inline void av_init_packet(AVPacket *pkt)
index 8fa014313eb9f2a8850a5595127fda6316b5d59e..caad4a00b9b7f170bc92bfe8d0570aa2b6cd663c 100644 (file)
@@ -165,7 +165,7 @@ AVInputFormat *av_find_input_format(const char *short_name)
 /**
  * Default packet destructor 
  */
-static void av_destruct_packet(AVPacket *pkt)
+void av_destruct_packet(AVPacket *pkt)
 {
     av_free(pkt->data);
     pkt->data = NULL; pkt->size = 0;
@@ -834,7 +834,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
         /* select current input stream component */
         st = s->cur_st;
         if (st) {
-            if (!st->parser) {
+            if (!st->need_parsing || !st->parser) {
                 /* no parsing needed: we just output the packet as is */
                 /* raw data support */
                 *pkt = s->cur_pkt;
@@ -876,7 +876,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                 /* return the last frames, if any */
                 for(i = 0; i < s->nb_streams; i++) {
                     st = s->streams[i];
-                    if (st->parser) {
+                    if (st->parser && st->need_parsing) {
                         av_parser_parse(st->parser, &st->codec, 
                                         &pkt->data, &pkt->size, 
                                         NULL, 0, 
@@ -1742,6 +1742,10 @@ int av_find_stream_info(AVFormatContext *ic)
             if(!st->codec.time_base.num)
                 st->codec.time_base= st->time_base;
         }
+        //only for the split stuff
+        if (!st->parser) {
+            st->parser = av_parser_init(st->codec.codec_id);
+        }
     }
 
     for(i=0;i<MAX_STREAMS;i++){
@@ -1762,6 +1766,8 @@ int av_find_stream_info(AVFormatContext *ic)
             if(   st->codec.time_base.den >= 1000LL*st->codec.time_base.num
                && duration_count[i]<20 && st->codec.codec_type == CODEC_TYPE_VIDEO)
                 break;
+            if(st->parser && st->parser->parser->split && !st->codec.extradata)
+                break;
         }
         if (i == ic->nb_streams) {
             /* NOTE: if the format has no header, then we need to read
@@ -1841,6 +1847,15 @@ int av_find_stream_info(AVFormatContext *ic)
             }
             last_dts[pkt->stream_index]= pkt->dts;
         }
+        if(st->parser && st->parser->parser->split && !st->codec.extradata){
+            int i= st->parser->parser->split(&st->codec, pkt->data, pkt->size);
+            if(i){
+                st->codec.extradata_size= i;
+                st->codec.extradata= av_malloc(st->codec.extradata_size);
+                memcpy(st->codec.extradata, pkt->data, st->codec.extradata_size);
+            }
+        }
+        
         /* if still no information, we try to open the codec and to
            decompress the frame. We try to avoid that in most cases as
            it takes longer and uses more memory. For MPEG4, we need to