Log in

View Full Version : Quick Mpeg/Vob scan


Zeul
23rd April 2004, 08:17
at the moment i am doing a byte by byte search of the video frames looking for the picture header; so that i can determine whether the video frame is either a I,P,B,D frame or just a part frame. Looking for the I frame is easy, because if the PES header length > 0 then it always seems to be an I frame, but this is not the case for the other 3 types. Although this approach works, it is slooooow. Can anyone suggest a better approach - are there offsets I should look for rather than just scanning for the picture header.

Approach:
Check sector for header - 0x000001E0
Check PES header length. If > 0 then I frame.
If Not > 0 then byte search from &H16 > Packet end, searching for
picture start code 0x00000100 and picture header code 0x000001B5

Thanks
Zeul

RB
23rd April 2004, 08:33
Just look at the DVD2AVIDG (http://neuron2.net/fixd2v/dvd2avidg100src.zip) sources. Anyway, to speed things up, you shouldn't probably read single bytes from the file but read larger chunks (2048 bytes) into some internal buffer and scan that buffer, getting the next chunk from the file into the buffer when necessary. DVD2AVI does just that.

ac-chan123
23rd April 2004, 15:06
In "Video Demystified - third edition" at site 583 is the start of the Picture Layer as follow defiened:

-picture start code:
-32 bit lenght wit an hex value of "00000100"

-Temoral reference:
-For the first frame in GOP, the 10 bit binary number is zero. It is then incremented by one, modulo 1024, for each frame in the display order. When the frame is coded as two fields, the temoral reference of both is filds is the same.

-Picture codeing Type
-3bit
000 forbidden
001 i Picture
010 P Picture
011 B Picture
100 forbidden
101-111 reserved

I hope this help.

AC-Chan(Robert Vincenz)

hank315
24th April 2004, 21:20
Because of the variable length coding there is no standard offset from one header until the next header.
AFAIK you have to scan for the picture headers, luckely they are byte aligned so you don't
have to do any bit operations except for the reading of the header itself.
The next lines show a complete program which scans a m2v, mpeg or vob file for picture headers,
the start address and type of the detected pictures are written into file 'output'.
I'm sorry, no C-code...
Just very simple (and fast) FORTRAN code with buffered file input.

!==================================================================
program IPBscan
integer(1) getbuf
integer(8) byteread
open(10,file= 'in.m2v',access='direct',recl=1024) ! open inputfile (direct access)
open(11,file= 'output') ! open sequential outputfile
byteread=0; i1=getbuf(); i2=getbuf(); i3=getbuf(); i4=getbuf() ! initialise
1 if (i1==0.and.i2==0.and.i3==1.and.i4==0) then ! found picture header (00 00 01 00)
do i=1,2; i1=i2; i2=i3; i3=i4; i4=getbuf(); enddo ! read next 2 bytes with picture type, skip temporal ref.
j=IBITS(i4,3,3) ! extract the 3 bits with the picture type starting at bit 3 (001=I, 010=P, 011=B) from last byte
if (j == 1) write(11,100) byteread,byteread ! I picture
if (j == 2) write(11,110) byteread,byteread ! P picture
if (j == 3) write(11,120) byteread,byteread ! B picture
byteread=byteread+2
endif
i1=i2; i2=i3; i3=i4; i4=getbuf(); byteread=byteread+1
goto 1 ! test next byte
100 format('I picture header start at byte:',i14,' (hex',Z12,')')
110 format('P picture header start at byte:',i14,' (hex',Z12,')')
120 format('B picture header start at byte:',i14,' (hex',Z12,')')
end
!==================================================================
integer(1) function getbuf
integer(1) buf(4096)
data irec,ibuf /1,999999/ ! initialise, save record number and buffer pointer
save buf ! save buffer for next function entry
if (ibuf > 4096) then ! buffer exhausted, read next record
read(10,rec=irec,err=999) buf; irec=irec+1; ibuf=1; endif
getbuf=buf(ibuf); ibuf=ibuf+1; return
999 close(10); close(11); stop ! EOF
end
!==================================================================


This program scans a VOB file of 1 GB in about 40 sec. on my PC with a processor load of 25%,
this means aprox. 25 MB/s IO, so disk IO seems to be crucial in this process.
Raising the buffer (now 4 KB) might improve speed.
An equivalent C-program with buffered input should be just as fast I think.

Hope this helps you out.

hank