From 1ff662cc2c542baf7acc3a78ac21e0f19a129320 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michaelni@gmx.at>
Date: Mon, 22 Apr 2002 19:04:28 +0000
Subject: [PATCH] export delay info fixed low_delay & vo_type on mpeg4 header
 writer & parser

Originally committed as revision 415 to svn://svn.ffmpeg.org/ffmpeg/trunk
---
 libavcodec/avcodec.h   |  7 +++++--
 libavcodec/h263.c      | 33 +++++++++++++++++++++++++++------
 libavcodec/h263dec.c   |  3 ++-
 libavcodec/mpeg4data.h |  3 +++
 libavcodec/mpegvideo.c | 10 ++++++++++
 libavcodec/mpegvideo.h |  2 ++
 6 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 10ebcaeb521..26e1b19abf4 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -5,8 +5,8 @@
 
 #define LIBAVCODEC_VERSION_INT 0x000406
 #define LIBAVCODEC_VERSION     "0.4.6"
-#define LIBAVCODEC_BUILD       4601
-#define LIBAVCODEC_BUILD_STR   "4601"
+#define LIBAVCODEC_BUILD       4602
+#define LIBAVCODEC_BUILD_STR   "4602"
 
 enum CodecID {
     CODEC_ID_NONE, 
@@ -140,6 +140,9 @@ typedef struct AVCodecContext {
     int frame_number; /* audio or video frame number */
     int key_frame;    /* true if the previous compressed frame was 
                          a key frame (intra, or seekable) */
+    int delay;        /* number of frames the decoded output will be delayed relative to the encoded input */
+    
+    /* encoding parameters */
     int quality;      /* quality of the previous encoded frame 
                          (between 1 (good) and 31 (bad)) 
                          this is allso used to set the quality in vbr mode
diff --git a/libavcodec/h263.c b/libavcodec/h263.c
index 305e80ddf63..7e3fec51819 100644
--- a/libavcodec/h263.c
+++ b/libavcodec/h263.c
@@ -1008,7 +1008,9 @@ static void mpeg4_encode_vol_header(MpegEncContext * s)
 {
     int vo_ver_id=1; //must be 2 if we want GMC or q-pel
     char buf[255];
-    
+
+    s->vo_type= s->has_b_frames ? CORE_VO_TYPE : SIMPLE_VO_TYPE;
+
     if(get_bit_count(&s->pb)!=0) mpeg4_stuffing(&s->pb);
     put_bits(&s->pb, 16, 0);
     put_bits(&s->pb, 16, 0x100);        /* video obj */
@@ -1016,7 +1018,7 @@ static void mpeg4_encode_vol_header(MpegEncContext * s)
     put_bits(&s->pb, 16, 0x120);        /* video obj layer */
 
     put_bits(&s->pb, 1, 0);		/* random access vol */
-    put_bits(&s->pb, 8, 1);		/* video obj type indication= simple obj */
+    put_bits(&s->pb, 8, s->vo_type);	/* video obj type indication */
     put_bits(&s->pb, 1, 1);		/* is obj layer id= yes */
       put_bits(&s->pb, 4, vo_ver_id);	/* is obj layer ver id */
       put_bits(&s->pb, 3, 1);		/* is obj layer priority */
@@ -1024,7 +1026,16 @@ static void mpeg4_encode_vol_header(MpegEncContext * s)
         put_bits(&s->pb, 4, s->aspect_ratio_info);/* aspect ratio info */
     else
         put_bits(&s->pb, 4, 1);		/* aspect ratio info= sqare pixel */
-    put_bits(&s->pb, 1, 0);		/* vol control parameters= no */
+
+    if(s->low_delay){
+        put_bits(&s->pb, 1, 1);		/* vol control parameters= yes */
+        put_bits(&s->pb, 2, 1);		/* chroma format 422 */
+        put_bits(&s->pb, 1, s->low_delay);
+        put_bits(&s->pb, 1, 0);		/* vbv parameters= no */
+    }else{
+        put_bits(&s->pb, 1, 0);		/* vol control parameters= no */
+    }
+
     put_bits(&s->pb, 2, RECT_SHAPE);	/* vol shape= rectangle */
     put_bits(&s->pb, 1, 1);		/* marker bit */
     
@@ -2579,7 +2590,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
 
         /* vol header */
         skip_bits(&s->gb, 1); /* random access */
-        skip_bits(&s->gb, 8); /* vo_type */
+        s->vo_type= get_bits(&s->gb, 8);
         if (get_bits1(&s->gb) != 0) { /* is_ol_id */
             vo_ver_id = get_bits(&s->gb, 4); /* vo_ver_id */
             skip_bits(&s->gb, 3); /* vo_priority */
@@ -2594,9 +2605,19 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
         }
 
         if(get_bits1(&s->gb)){ /* vol control parameter */
-            printf("vol control parameter not supported\n");
-            return -1;   
+            int chroma_format= get_bits(&s->gb, 2);
+            if(chroma_format!=1){
+                printf("illegal chroma format\n");
+            }
+            s->low_delay= get_bits1(&s->gb);
+            if(get_bits1(&s->gb)){ /* vbv parameters */
+                printf("vbv parameters not supported\n");
+                return -1;
+            }
+        }else{
+            s->low_delay=0;
         }
+
         s->shape = get_bits(&s->gb, 2); /* vol shape */
         if(s->shape != RECT_SHAPE) printf("only rectangular vol supported\n");
         if(s->shape == GRAY_SHAPE && vo_ver_id != 1){
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index b3e11b9bcd4..9b8606d5e79 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -45,7 +45,7 @@ static int h263_decode_init(AVCodecContext *avctx)
     case CODEC_ID_MPEG4:
         s->time_increment_bits = 4; /* default value for broken headers */
         s->h263_pred = 1;
-        s->has_b_frames = 1;
+        s->has_b_frames = 1; //default, might be overriden in the vol header during header parsing
         break;
     case CODEC_ID_MSMPEG4V1:
         s->h263_msmpeg4 = 1;
@@ -129,6 +129,7 @@ static int h263_decode_frame(AVCodecContext *avctx,
         ret = msmpeg4_decode_picture_header(s);
     } else if (s->h263_pred) {
         ret = mpeg4_decode_picture_header(s);
+        s->has_b_frames= !s->low_delay;
     } else if (s->h263_intel) {
         ret = intel_h263_decode_picture_header(s);
     } else {
diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h
index d94b1d9efec..831cf4b41b9 100644
--- a/libavcodec/mpeg4data.h
+++ b/libavcodec/mpeg4data.h
@@ -4,6 +4,9 @@
 #define BIN_ONLY_SHAPE   2
 #define GRAY_SHAPE       3
 
+#define SIMPLE_VO_TYPE 1
+#define CORE_VO_TYPE   3
+
 // aspect_ratio_info
 #define EXTENDET_PAR 15
 
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 5885fd73d2b..ec1c0f9f05c 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -409,6 +409,7 @@ int MPV_encode_init(AVCodecContext *avctx)
     switch(avctx->codec->id) {
     case CODEC_ID_MPEG1VIDEO:
         s->out_format = FMT_MPEG1;
+        avctx->delay=0; //FIXME not sure, should check the spec
         break;
     case CODEC_ID_MJPEG:
         s->out_format = FMT_MJPEG;
@@ -422,6 +423,7 @@ int MPV_encode_init(AVCodecContext *avctx)
         s->mjpeg_hsample[2] = 1; 
         if (mjpeg_init(s) < 0)
             return -1;
+        avctx->delay=0;
         break;
     case CODEC_ID_H263:
         if (h263_get_picture_format(s->width, s->height) == 7) {
@@ -429,6 +431,7 @@ int MPV_encode_init(AVCodecContext *avctx)
             return -1;
         }
         s->out_format = FMT_H263;
+        avctx->delay=0;
         break;
     case CODEC_ID_H263P:
         s->out_format = FMT_H263;
@@ -440,16 +443,20 @@ int MPV_encode_init(AVCodecContext *avctx)
         /* These are just to be sure */
         s->umvplus = 0;
         s->umvplus_dec = 0;
+        avctx->delay=0;
         break;
     case CODEC_ID_RV10:
         s->out_format = FMT_H263;
         s->h263_rv10 = 1;
+        avctx->delay=0;
         break;
     case CODEC_ID_MPEG4:
         s->out_format = FMT_H263;
         s->h263_pred = 1;
         s->unrestricted_mv = 1;
         s->has_b_frames= s->max_b_frames ? 1 : 0;
+        s->low_delay=0;
+        avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); 
         break;
     case CODEC_ID_MSMPEG4V1:
         s->out_format = FMT_H263;
@@ -457,6 +464,7 @@ int MPV_encode_init(AVCodecContext *avctx)
         s->h263_pred = 1;
         s->unrestricted_mv = 1;
         s->msmpeg4_version= 1;
+        avctx->delay=0;
         break;
     case CODEC_ID_MSMPEG4V2:
         s->out_format = FMT_H263;
@@ -464,6 +472,7 @@ int MPV_encode_init(AVCodecContext *avctx)
         s->h263_pred = 1;
         s->unrestricted_mv = 1;
         s->msmpeg4_version= 2;
+        avctx->delay=0;
         break;
     case CODEC_ID_MSMPEG4V3:
         s->out_format = FMT_H263;
@@ -471,6 +480,7 @@ int MPV_encode_init(AVCodecContext *avctx)
         s->h263_pred = 1;
         s->unrestricted_mv = 1;
         s->msmpeg4_version= 3;
+        avctx->delay=0;
         break;
     default:
         return -1;
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index c5335aba195..6b678233427 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -296,6 +296,8 @@ typedef struct MpegEncContext {
     int data_partioning;
     int resync_marker;
     int resync_x_pos;
+    int low_delay;                   /* no reordering needed / has no b-frames */
+    int vo_type;
 
     /* divx specific, used to workaround (many) bugs in divx5 */
     int divx_version;
-- 
GitLab