0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 20:03:10 +02:00

automatic fps calculation for mpeg4 in raw stream/mpeg-ts

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@14478 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
nicodvb 2005-01-12 20:43:53 +00:00
parent 55689c29a6
commit 70a7a6b450
3 changed files with 166 additions and 2 deletions

View File

@ -27,7 +27,7 @@ int mp_header_process_sequence_header (mp_mpeg_header_t * picture, unsigned char
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 @@ int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buf
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);
}

View File

@ -15,7 +15,12 @@ typedef struct {
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);
int mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer);

View File

@ -116,6 +116,7 @@ switch(video_codec){
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 @@ switch(video_codec){
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 @@ switch(video_codec){
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;