changeset 942:c237f5db1c22 libavcodec

correcter mpeg4 headers
author michaelni
date Mon, 30 Dec 2002 00:28:42 +0000
parents 1e4ab5fdfca1
children 0566d1a8426f
files avcodec.h h263.c mpeg4data.h mpegvideo.h
diffstat 4 files changed, 136 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/avcodec.h	Sun Dec 29 23:31:52 2002 +0000
+++ b/avcodec.h	Mon Dec 30 00:28:42 2002 +0000
@@ -826,8 +826,10 @@
 #define FF_DEBUG_MB_TYPE   8
 #define FF_DEBUG_QP        16
 #define FF_DEBUG_MV        32
-#define FF_DEBUG_VIS_MV    64
-#define FF_DEBUG_SKIP      128
+#define FF_DEBUG_VIS_MV    0x00000040
+#define FF_DEBUG_SKIP      0x00000080
+#define FF_DEBUG_STARTCODE 0x00000100
+#define FF_DEBUG_PTS       0x00000200
     
     /**
      * error
--- a/h263.c	Sun Dec 29 23:31:52 2002 +0000
+++ b/h263.c	Mon Dec 30 00:28:42 2002 +0000
@@ -1564,21 +1564,77 @@
     }
 }
 
-static void mpeg4_encode_vol_header(MpegEncContext * s)
+static void mpeg4_encode_gop_header(MpegEncContext * s){
+    int hours, minutes, seconds;
+    
+    put_bits(&s->pb, 16, 0);
+    put_bits(&s->pb, 16, GOP_STARTCODE);
+    
+    seconds= s->time/s->time_increment_resolution;
+    minutes= seconds/60; seconds %= 60;
+    hours= minutes/60; minutes %= 60;
+    hours%=24;
+
+    put_bits(&s->pb, 5, hours);
+    put_bits(&s->pb, 6, minutes);
+    put_bits(&s->pb, 1, 1);
+    put_bits(&s->pb, 6, seconds);
+    
+    put_bits(&s->pb, 1, 0); //closed gov == NO
+    put_bits(&s->pb, 1, 0); //broken link == NO
+
+    ff_mpeg4_stuffing(&s->pb);
+}
+
+static void mpeg4_encode_visual_object_header(MpegEncContext * s){
+    int profile_and_level_indication;
+    int vo_ver_id;
+    
+    if(s->max_b_frames || s->quarter_sample){
+        profile_and_level_indication= 0xF1; // adv simple level 1
+        vo_ver_id= 5;
+    }else{
+        profile_and_level_indication= 0x01; // simple level 1
+        vo_ver_id= 1;
+    }
+    //FIXME levels
+
+    put_bits(&s->pb, 16, 0);
+    put_bits(&s->pb, 16, VOS_STARTCODE);
+    
+    put_bits(&s->pb, 8, profile_and_level_indication);
+    
+    put_bits(&s->pb, 16, 0);
+    put_bits(&s->pb, 16, VISUAL_OBJ_STARTCODE);
+    
+    put_bits(&s->pb, 1, 1);
+        put_bits(&s->pb, 4, vo_ver_id);
+        put_bits(&s->pb, 3, 1); //priority
+ 
+    put_bits(&s->pb, 4, 1); //visual obj type== video obj
+    
+    put_bits(&s->pb, 1, 0); //video signal type == no clue //FIXME
+
+    ff_mpeg4_stuffing(&s->pb);
+}
+
+static void mpeg4_encode_vol_header(MpegEncContext * s, int vo_number, int vol_number)
 {
-    int vo_ver_id=2; //must be 2 if we want GMC or q-pel
+    int vo_ver_id;
     char buf[255];
 
-    if(s->max_b_frames){
+    if(s->max_b_frames || s->quarter_sample){
+        vo_ver_id= 5;
         s->vo_type= ADV_SIMPLE_VO_TYPE;
     }else{
+        vo_ver_id= 1;
         s->vo_type= SIMPLE_VO_TYPE;
     }
 
     put_bits(&s->pb, 16, 0);
-    put_bits(&s->pb, 16, 0x100);        /* video obj */
+    put_bits(&s->pb, 16, 0x100 + vo_number);        /* video obj */
     put_bits(&s->pb, 16, 0);
-    put_bits(&s->pb, 16, 0x120);        /* video obj layer */
+    put_bits(&s->pb, 16, 0x120 + vol_number);       /* video obj layer */
 
     put_bits(&s->pb, 1, 0);		/* random access vol */
     put_bits(&s->pb, 8, s->vo_type);	/* video obj type indication */
@@ -1621,7 +1677,7 @@
     put_bits(&s->pb, 1, 1);		/* obmc disable */
     if (vo_ver_id == 1) {
         put_bits(&s->pb, 1, s->vol_sprite_usage=0);		/* sprite enable */
-    }else{ /* vo_ver_id == 2 */
+    }else{
         put_bits(&s->pb, 2, s->vol_sprite_usage=0);		/* sprite enable */
     }
     
@@ -1665,8 +1721,13 @@
     int time_div, time_mod;
     
     if(s->pict_type==I_TYPE){
-        if(picture_number==0 || !s->strict_std_compliance)
-            mpeg4_encode_vol_header(s);
+        if(picture_number - s->last_vo_picture_number >= 300 || picture_number==0){
+            mpeg4_encode_visual_object_header(s);
+            mpeg4_encode_vol_header(s, 0, 0);
+
+            s->last_vo_picture_number= picture_number;
+        }
+        mpeg4_encode_gop_header(s);
     }
     
     s->partitioned_frame= s->data_partitioning && s->pict_type!=B_TYPE;
@@ -1674,7 +1735,7 @@
 //printf("num:%d rate:%d base:%d\n", s->picture_number, s->frame_rate, FRAME_RATE_BASE);
     
     put_bits(&s->pb, 16, 0);	        /* vop header */
-    put_bits(&s->pb, 16, 0x1B6);	/* vop header */
+    put_bits(&s->pb, 16, VOP_STARTCODE);	/* vop header */
     put_bits(&s->pb, 2, s->pict_type - 1);	/* pict type: I = 0 , P = 1 */
 
     time_div= s->time/s->time_increment_resolution;
@@ -4147,6 +4208,22 @@
 #endif
 }
 
+static int mpeg4_decode_gop_header(MpegEncContext * s, GetBitContext *gb){
+    int hours, minutes, seconds;
+
+    hours= get_bits(gb, 5);
+    minutes= get_bits(gb, 6);
+    skip_bits1(gb);
+    seconds= get_bits(gb, 6);
+
+    s->time_base= seconds + 60*(minutes + 60*hours);
+
+    skip_bits1(gb);
+    skip_bits1(gb);
+    
+    return 0;
+}
+
 static int decode_vol_header(MpegEncContext *s, GetBitContext *gb){
     int width, height, vo_ver_id;
 
@@ -4504,6 +4581,8 @@
     }
     
     s->current_picture.pts= s->time*1000LL*1000LL / s->time_increment_resolution;
+    if(s->avctx->debug&FF_DEBUG_PTS)
+        printf("MPEG4 PTS: %f\n", s->current_picture.pts/(1000.0*1000.0));
     
     if(check_marker(gb, "before vop_coded")==0 && s->picture_number==0){
         printf("hmm, seems the headers arnt complete, trying to guess time_increment_bits\n");
@@ -4668,17 +4747,51 @@
         if((startcode&0xFFFFFF00) != 0x100)
             continue; //no startcode
         
+        if(s->avctx->debug&FF_DEBUG_STARTCODE){
+            printf("startcode: %3X ", startcode);
+            if     (startcode<=0x11F) printf("Video Object Start");
+            else if(startcode<=0x12F) printf("Video Object Layer Start");
+            else if(startcode<=0x13F) printf("Reserved");
+            else if(startcode<=0x15F) printf("FGS bp start");
+            else if(startcode<=0x1AF) printf("Reserved");
+            else if(startcode==0x1B0) printf("Visual Object Seq Start");
+            else if(startcode==0x1B1) printf("Visual Object Seq End");
+            else if(startcode==0x1B2) printf("User Data");
+            else if(startcode==0x1B3) printf("Group of VOP start");
+            else if(startcode==0x1B4) printf("Video Session Error");
+            else if(startcode==0x1B5) printf("Visual Object Start");
+            else if(startcode==0x1B6) printf("Video Object Plane start");
+            else if(startcode==0x1B7) printf("slice start");
+            else if(startcode==0x1B8) printf("extension start");
+            else if(startcode==0x1B9) printf("fgs start");
+            else if(startcode==0x1BA) printf("FBA Object start");
+            else if(startcode==0x1BB) printf("FBA Object Plane start");
+            else if(startcode==0x1BC) printf("Mesh Object start");
+            else if(startcode==0x1BD) printf("Mesh Object Plane start");
+            else if(startcode==0x1BE) printf("Still Textutre Object start");
+            else if(startcode==0x1BF) printf("Textutre Spatial Layer start");
+            else if(startcode==0x1C0) printf("Textutre SNR Layer start");
+            else if(startcode==0x1C1) printf("Textutre Tile start");
+            else if(startcode==0x1C2) printf("Textutre Shape Layer start");
+            else if(startcode==0x1C3) printf("stuffing start");
+            else if(startcode<=0x1C5) printf("reserved");
+            else if(startcode<=0x1FF) printf("System start");
+            printf(" at %d\n", get_bits_count(gb));
+        }
+
         switch(startcode){
         case 0x120:
             decode_vol_header(s, gb);
             break;
-        case 0x1b2:
+        case USER_DATA_STARTCODE:
             decode_user_data(s, gb);
             break;
-        case 0x1b6:
+        case GOP_STARTCODE:
+            mpeg4_decode_gop_header(s, gb);
+            break;
+        case VOP_STARTCODE:
             return decode_vop_header(s, gb);
         default:
-//            printf("startcode %X found\n", startcode);
             break;
         }
 
--- a/mpeg4data.h	Sun Dec 29 23:31:52 2002 +0000
+++ b/mpeg4data.h	Mon Dec 30 00:28:42 2002 +0000
@@ -27,6 +27,12 @@
 #define MB_TYPE_B_BACKW  2
 #define MB_TYPE_B_FORW   3
 
+#define VOS_STARTCODE        0x1B0
+#define USER_DATA_STARTCODE  0x1B2
+#define GOP_STARTCODE        0x1B3
+#define VISUAL_OBJ_STARTCODE 0x1B5
+#define VOP_STARTCODE        0x1B6
+
 /* dc encoding for mpeg4 */
 const UINT8 DCtab_lum[13][2] =
 {
--- a/mpegvideo.h	Sun Dec 29 23:31:52 2002 +0000
+++ b/mpegvideo.h	Mon Dec 30 00:28:42 2002 +0000
@@ -435,6 +435,7 @@
     INT8 (*field_select_table)[2];   /* wtf, no really another table for interlaced b frames */
     int t_frame;                     /* time distance of first I -> B, used for interlaced b frames */
     int padding_bug_score;           /* used to detect the VERY common padding bug in MPEG4 */
+    int last_vo_picture_number;      /* last picture number for which we added a VOS/VO/VOL header */
 
     /* divx specific, used to workaround (many) bugs in divx5 */
     int divx_version;