[MPlayer-dev-eng] [PATCH] automatic fps for mpeg4 raw/in TS

Nico Sabbi nsabbi at tiscali.it
Tue Jan 11 21:27:20 CET 2005


Nico Sabbi wrote:

> Nico Sabbi wrote:
>
>> Nico Sabbi wrote:
>>
>>> Michael Niedermayer wrote:
>>>
>>>> Hi
>>>>
>>>> On Wednesday 05 January 2005 23:12, Nico Sabbi wrote:
>>>>  
>>>>
>>>>> Michael Niedermayer wrote:
>>>>>  
>>>>>
>>>>>> Hi
>>>>>>
>>>>>> On Wednesday 05 January 2005 22:09, Nico Sabbi wrote:
>>>>>>   
>>>>>>
>>>>>>> Hi,
>>>>>>> this patch permits to determine automatically the initial fps of 
>>>>>>> mpeg4
>>>>>>> video in the VOL header,
>>>>>>> so there's no need to specify it with -fps.
>>>>>>>
>>>>>>> Michael, can you please check it?
>>>>>>>       
>>>>>>
>>>>>>
>>>>>>
>>>>>> did u try it with a few different framerates like a 24000/1001 
>>>>>> .m4v stream
>>>>>> generated by ffmpeg? i doubt it will work
>>>>>>
>>>>>> [...]
>>>>>>     
>>>>>
>>>>>
>>>>>
>>>>> I checked some fancy fps but not the fractional ones; now I see they
>>>>> aren't recognized
>>>>> correctly.
>>>>> If I understand correctly the specs the fixed_timeinc is given by the
>>>>> smallest
>>>>> number of bits (up to 16) to represent   timeinc_resolution-1, 
>>>>> correct ?
>>>>>   
>>>>
>>>>
>>>>
>>>>
>>>> IIRC, yes
>>>>
>>>>
>>>>  
>>>>
>>>>> What's wrong? :)
>>>>>   
>>>>
>>>>
>>>>
>>>>
>>>> many mpeg4 files have no fixed_timeinc
>>>> [...]
>>>>  
>>>>
>>>
>>> This one works correctly with all fps I tried, both with lavc and 
>>> with xvid, in raw files and in TS.
>>> Is it ok ?
>>>
>>>    Nico
>>
>>
>>
>>
>> sorry, this doesn't work with b-frames :(
>> next time ...
>>
>
> given that 3 consecutive frames are always enough to determine the 
> smallest delta_timeinc
> (or I'm mistaken?) this patch should work correctly (it does for me, 
> even seeking with -sb).
> Michael, what's your opinion?
>
>------------------------------------------------------------------------
>
>Index: mpeg_hdr.c
>===================================================================
>RCS file: /cvsroot/mplayer/main/libmpdemux/mpeg_hdr.c,v
>retrieving revision 1.5
>diff -c -u -r1.5 mpeg_hdr.c
>--- mpeg_hdr.c	3 Jul 2004 11:38:56 -0000	1.5
>+++ mpeg_hdr.c	7 Jan 2005 09:04:21 -0000
>@@ -27,7 +27,7 @@
>     int width, height;
> 
>     if ((buffer[6] & 0x20) != 0x20){
>-	printf("missing marker bit!\n");
>+	fprintf(stderr, "missing marker bit!\n");
> 	return 1;	/* missing marker_bit */
>     }
> 
>@@ -101,3 +101,112 @@
>     return 0;
> }
> 
>+
>+//MPEG4 HEADERS
>+static unsigned char getbits(unsigned char *buffer, unsigned int from, unsigned char len)
>+{
>+    unsigned int n;
>+    unsigned char m, u, l, y;
>+    
>+    n = from / 8;
>+    m = from % 8;
>+    u = 8 - m;
>+    l = (len > u ? len - u : 0);
>+    
>+    y = (buffer[n] << m);
>+    if(8 > len)
>+    	y  >>= (8-len);
>+    if(l)
>+    	y |= (buffer[n+1] >> (8-l));
>+	
>+    //fprintf(stderr, "GETBITS(%d -> %d): bytes=0x%x 0x%x, n=%d, m=%d, l=%d, u=%d, Y=%d\n", 
>+    //	from, (int) len, (int) buffer[n],(int) buffer[n+1], n, (int) m, (int) l, (int) u, (int) y);
>+    return  y;
>+}
>+
>+static int read_timeinc(mp_mpeg_header_t * picture, unsigned char * buffer, int n)
>+{
>+    if(picture->timeinc_bits > 8) {
>+      picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits - 8) << 8;
>+      n += picture->timeinc_bits - 8;
>+      picture->timeinc_unit |= getbits(buffer, n, 8);
>+      n += 8;
>+    } else {
>+      picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits);
>+      n += picture->timeinc_bits;
>+    }
>+    //fprintf(stderr, "TIMEINC2: %d, bits: %d\n", picture->timeinc_unit, picture->timeinc_bits);
>+    return n;
>+}
>+
>+int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer)
>+{
>+    unsigned int n, aspect=0, aspectw=0, aspecth=0,  x=1, v;
>+    
>+    //begins with 0x0000012x
>+    picture->fps = 0;
>+    picture->timeinc_bits = picture->timeinc_resolution = picture->timeinc_unit = 0;
>+    n = 9;
>+    if(getbits(buffer, n, 1))
>+      n += 7;
>+    n++;
>+    aspect=getbits(buffer, n, 4);
>+    n += 4;
>+    if(aspect == 0x0f) {
>+      aspectw = getbits(buffer, n, 8);
>+      n += 8;
>+      aspecth = getbits(buffer, n, 8);
>+      n += 8;
>+    }
>+    
>+    if(getbits(buffer, n, 1)) {
>+      n += 4;
>+      if(getbits(buffer, n, 1))
>+        n += 79;
>+      n++;
>+    } else n++;
>+    
>+    n+=3;
>+    
>+    picture->timeinc_resolution = getbits(buffer, n, 8) << 8;
>+    n += 8;
>+    picture->timeinc_resolution |= getbits(buffer, n, 8);
>+    n += 8;
>+    
>+    picture->timeinc_bits = 0;
>+    v = picture->timeinc_resolution - 1;
>+    while(v && (x<16)) {
>+      v>>=1;
>+      picture->timeinc_bits++;
>+    }
>+    picture->timeinc_bits = (picture->timeinc_bits > 1 ? picture->timeinc_bits : 1);
>+    
>+    n++; //marker bit
>+    
>+    if(getbits(buffer, n, 1)) {	//fixed_vop_timeinc
>+      n++;
>+      n = read_timeinc(picture, buffer, n);
>+      
>+      if(picture->timeinc_unit)
>+        picture->fps = (picture->timeinc_resolution * 10000) / picture->timeinc_unit;
>+    }
>+    
>+    //fprintf(stderr, "ASPECT: %d, PARW=%d, PARH=%d, TIMEINCRESOLUTION: %d, FIXED_TIMEINC: %d (number of bits: %d), FPS: %u\n", 
>+    //	aspect, aspectw, aspecth, picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_bits, picture->fps);
>+    
>+    return 0;
>+}
>+
>+int mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer)
>+{
>+  int n;
>+  n = 0;
>+  picture->picture_type = getbits(buffer, n, 2);
>+  n += 2;
>+  while(getbits(buffer, n, 1))
>+    n++;
>+  n++;
>+  getbits(buffer, n, 1);
>+  n++;
>+  n = read_timeinc(picture, buffer, n);
>+}
>Index: mpeg_hdr.h
>===================================================================
>RCS file: /cvsroot/mplayer/main/libmpdemux/mpeg_hdr.h,v
>retrieving revision 1.1
>diff -c -u -r1.1 mpeg_hdr.h
>--- mpeg_hdr.h	30 Oct 2001 18:45:54 -0000	1.1
>+++ mpeg_hdr.h	7 Jan 2005 09:04:21 -0000
>@@ -15,7 +15,11 @@
>     int progressive_frame;
>     int top_field_first;
>     int display_time; // secs*100
>+    //the following are for mpeg4
>+    int timeinc_resolution, timeinc_bits, timeinc_unit;
>+    int picture_type;
> } mp_mpeg_header_t;
> 
> int mp_header_process_sequence_header (mp_mpeg_header_t * picture, unsigned char * buffer);
> int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer);
>+int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer);
>Index: video.c
>===================================================================
>RCS file: /cvsroot/mplayer/main/libmpdemux/video.c,v
>retrieving revision 1.47
>diff -c -u -r1.47 video.c
>--- video.c	24 Nov 2004 18:55:03 -0000	1.47
>+++ video.c	7 Jan 2005 09:04:21 -0000
>@@ -116,6 +116,7 @@
>   break;
>  }
>  case VIDEO_MPEG4: {
>+   int pos = 0, vop_cnt=0, units[3];
>    videobuf_len=0; videobuf_code_len=0;
>    mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Start code... ");fflush(stdout);
>    while(1){
>@@ -142,7 +143,14 @@
> 	return 0;
>       }
>    }
>-   mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\nSearching for Video Object Plane Start code... ");fflush(stdout);
>+   pos = videobuf_len+4;
>+   if(!read_video_packet(d_video)){ 
>+     mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Layer Header\n");
>+     return 0;
>+   }
>+   mp4_header_process_vol(&picture, &(videobuffer[pos]));
>+   mp_msg(MSGT_DECVIDEO,MSGL_V,"OK! FPS SEEMS TO BE %.3f\nSearching for Video Object Plane Start code... ", sh_video->fps);fflush(stdout);
>+ mp4_init: 
>    while(1){
>       int i=sync_video_packet(d_video);
>       if(i==0x1B6) break; // found it!
>@@ -151,6 +159,48 @@
> 	return 0;
>       }
>    }
>+   pos = videobuf_len+4;
>+   if(!read_video_packet(d_video)){ 
>+     mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Plane Header\n");
>+     return 0;
>+   }
>+   mp4_header_process_vop(&picture, &(videobuffer[pos]));
>+   units[vop_cnt] = picture.timeinc_unit;
>+   vop_cnt++;
>+   //mp_msg(MSGT_DECVIDEO,MSGL_V, "TYPE: %d, unit: %d\n", picture.picture_type, picture.timeinc_unit);
>+   if(!picture.fps) {
>+     int i, mn, md, mx, diff;
>+     if(vop_cnt < 3)
>+          goto mp4_init;
>+
>+     i=0;
>+     mn = mx = units[0];  
>+     for(i=0; i<3; i++) {
>+       if(units[i] < mn)
>+         mn = units[i];
>+       if(units[i] > mx)
>+         mx = units[i];
>+     }
>+     md = mn;
>+     for(i=0; i<3; i++) {
>+       if((units[i] > mn) && (units[i] < mx))
>+         md = units[i];
>+     }
>+     mp_msg(MSGT_DECVIDEO,MSGL_V, "MIN: %d, mid: %d, max: %d\n", mn, md, mx);
>+     if(mx - md > md - mn)
>+       diff = md - mn;
>+     else
>+       diff = mx - md;
>+     if(diff > 0){
>+       picture.fps = (picture.timeinc_resolution * 10000) / (diff);
>+       mp_msg(MSGT_DECVIDEO,MSGL_V, "FPS seems to be: %d/10000, resolution: %d, delta_units: %d\n", picture.fps, picture.timeinc_resolution, diff);
>+     }
>+   }
>+   if(picture.fps) {
>+    sh_video->fps=picture.fps*0.0001f;
>+    sh_video->frametime=10000.0f/(float)picture.fps;
>+    mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %d/10000\n", picture.fps);
>+   }
>    mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
>    sh_video->format=0x10000004;
>    break;
>  
>
>------------------------------------------------------------------------
>
>  
>

Michael, any comment on this patch or should I consider it rejected?
In this last case what other method can you advise?
Thanks,
    Nico




More information about the MPlayer-dev-eng mailing list