mirror of
https://github.com/mpv-player/mpv
synced 2024-12-18 12:55:16 +00: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:
parent
55689c29a6
commit
70a7a6b450
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user