[MPlayer-cvslog] CVS: main/libmpdemux mpeg_hdr.c, 1.6, 1.7 mpeg_hdr.h, 1.2, 1.3 video.c, 1.48, 1.49
Nico Sabbi CVS
syncmail at mplayerhq.hu
Thu Feb 24 21:02:43 CET 2005
CVS change done by Nico Sabbi CVS
Update of /cvsroot/mplayer/main/libmpdemux
In directory mail:/var2/tmp/cvs-serv23502
Modified Files:
mpeg_hdr.c mpeg_hdr.h video.c
Log Message:
framerate autodetection for H264 in raw/ts streams
Index: mpeg_hdr.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/mpeg_hdr.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- mpeg_hdr.c 12 Jan 2005 20:43:53 -0000 1.6
+++ mpeg_hdr.c 24 Feb 2005 20:02:41 -0000 1.7
@@ -210,3 +210,151 @@
n++;
n = read_timeinc(picture, buffer, n);
}
+
+#define min(a, b) ((a) <= (b) ? (a) : (b))
+
+static unsigned int read_golomb(unsigned char *buffer, unsigned int *init)
+{
+ unsigned int x, v = 0, v2 = 0, m, len = 0, n = *init;
+
+ while(getbits(buffer, n++, 1) == 0)
+ len++;
+
+ x = len + n;
+ while(n < x)
+ {
+ m = min(x - n, 8);
+ v |= getbits(buffer, n, m);
+ n += m;
+ if(x - n > 8)
+ v <<= 8;
+ }
+
+ v2 = 1;
+ for(n = 0; n < len; n++)
+ v2 <<= 1;
+ v2 = (v2 - 1) + v;
+
+ //fprintf(stderr, "READ_GOLOMB(%u), V=2^%u + %u-1 = %u\n", *init, len, v, v2);
+ *init = x;
+ return v2;
+}
+
+
+static int h264_parse_vui(mp_mpeg_header_t * picture, unsigned char * buf, unsigned int n)
+{
+ unsigned int overscan, vsp_color, chroma, timing, fixed_fps;
+
+ if(getbits(buf, n++, 1))
+ {
+ picture->aspect_ratio_information = getbits(buf, n, 8);
+ n += 8;
+ if(picture->aspect_ratio_information == 255)
+ {
+ picture->display_picture_width = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8);
+ n += 16;
+
+ picture->display_picture_height = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8);
+ n += 16;
+ }
+ }
+
+ if(overscan=getbits(buf, n++, 1))
+ n++;
+ if(vsp_color=getbits(buf, n++, 1))
+ {
+ n += 4;
+ if(getbits(buf, n++, 1))
+ n += 24;
+ }
+ if(chroma=getbits(buf, n++, 1))
+ {
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ }
+ if(timing=getbits(buf, n++, 1))
+ {
+ picture->timeinc_unit = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8);
+ n += 32;
+
+ picture->timeinc_resolution = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8);
+ n += 32;
+
+ fixed_fps = getbits(buf, n, 1);
+
+ if(picture->timeinc_unit > 0 && picture->timeinc_resolution > 0)
+ picture->fps = (picture->timeinc_resolution * 10000) / picture->timeinc_unit;
+ }
+
+ //fprintf(stderr, "H264_PARSE_VUI, OVESCAN=%u, VSP_COLOR=%u, CHROMA=%u, TIMING=%u, DISPW=%u, DISPH=%u, TIMERES=%u, TIMEINC=%u, FIXED_FPS=%u\n", overscan, vsp_color, chroma, timing, picture->display_picture_width, picture->display_picture_height,
+ // picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_unit, fixed_fps);
+
+ return n;
+}
+
+int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len)
+{
+ unsigned int n = 0, m = 0, v, i, j;
+ unsigned char *dest;
+
+ dest = (unsigned char*) malloc(len);
+ if(! dest)
+ return 0;
+ j = i = 0;
+ while(i <= len-3)
+ {
+ if(buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 3)
+ {
+ dest[j] = dest[j+1] = 0;
+ j += 2;
+ i += 3;
+ }
+ else
+ {
+ dest[j] = buf[i];
+ j++;
+ i++;
+ }
+ }
+ dest[j] = buf[len-2];
+ dest[j+1] = buf[len-1];
+ j += 2;
+ len = j+1;
+ buf = dest;
+
+ picture->fps = picture->timeinc_unit = picture->timeinc_resolution = 0;
+ n = 24;
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ v = read_golomb(buf, &n);
+ if(v == 0)
+ read_golomb(buf, &n);
+ else if(v == 1)
+ {
+ getbits(buf, n++, 1);
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ v = read_golomb(buf, &n);
+ for(i = 0; i < v; i++)
+ read_golomb(buf, &n);
+ }
+ read_golomb(buf, &n);
+ getbits(buf, n++, 1);
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ if(!getbits(buf, n++, 1))
+ getbits(buf, n++, 1);
+ getbits(buf, n++, 1);
+ if(getbits(buf, n++, 1))
+ {
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ read_golomb(buf, &n);
+ }
+ if(getbits(buf, n++, 1))
+ n = h264_parse_vui(picture, buf, n);
+
+ free(dest);
+ return n;
+}
Index: mpeg_hdr.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/mpeg_hdr.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- mpeg_hdr.h 12 Jan 2005 20:43:53 -0000 1.2
+++ mpeg_hdr.h 24 Feb 2005 20:02:41 -0000 1.3
@@ -24,3 +24,4 @@
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);
+int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len);
Index: video.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/video.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- video.c 12 Jan 2005 20:43:52 -0000 1.48
+++ video.c 24 Feb 2005 20:02:41 -0000 1.49
@@ -206,6 +206,7 @@
break;
}
case VIDEO_H264: {
+ int pos = 0;
videobuf_len=0; videobuf_code_len=0;
mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence parameter set... ");fflush(stdout);
while(1){
@@ -222,6 +223,12 @@
mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_ShMemAllocFail);
return 0;
}
+ pos = videobuf_len+4;
+ if(!read_video_packet(d_video)){
+ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read sequence parameter set\n");
+ return 0;
+ }
+ h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos);
mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for picture parameter set... ");fflush(stdout);
while(1){
int i=sync_video_packet(d_video);
@@ -243,6 +250,11 @@
}
mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
sh_video->format=0x10000005;
+ 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);
+ }
break;
}
case VIDEO_MPEG12: {
@@ -495,7 +507,19 @@
//
while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
int i=sync_video_packet(d_video);
+ int pos = videobuf_len+4;
+ if(!i) return -1;
if(!read_video_packet(d_video)) return -1; // EOF
+ if((i&~0x60) == 0x107 && i != 0x107) {
+ h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos);
+ if(picture.fps > 0) {
+ sh_video->fps=picture.fps*0.0001f;
+ sh_video->frametime=10000.0f/(float)picture.fps;
+ }
+ i=sync_video_packet(d_video);
+ if(!i) return -1;
+ if(!read_video_packet(d_video)) return -1; // EOF
+ }
if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105) break;
}
*start=videobuffer; in_size=videobuf_len;
More information about the MPlayer-cvslog
mailing list