# HG changeset patch # User michaelni # Date 1041208122 0 # Node ID c237f5db1c224aa459b2ded119ea2e1e7b27c55d # Parent 1e4ab5fdfca1d72ca9570e21c3f3d3135b4833ee correcter mpeg4 headers diff -r 1e4ab5fdfca1 -r c237f5db1c22 avcodec.h --- 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 diff -r 1e4ab5fdfca1 -r c237f5db1c22 h263.c --- 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; } diff -r 1e4ab5fdfca1 -r c237f5db1c22 mpeg4data.h --- 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] = { diff -r 1e4ab5fdfca1 -r c237f5db1c22 mpegvideo.h --- 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;