[Ffmpeg-devel] dvr-ms seek help request

John Donaghy johnfdonaghy
Wed Mar 22 00:21:08 CET 2006


Hi

dvr-ms files can now play in the likes of mplayer using the ffmpeg asf
demuxer. However seeking doesn't work well because key frames cant be
detected.

I've being trying to fix this without much success so I'm hoping for
suggestions from anyone who might be able to help. First off - is
there an asf expert in the house or is this a dead format as far as
anyone here is concerned? If you dont care about asf format then I'm
sure the following will be of no interest to you. I only got
interested in it because I currently record TV in the format that I
want to watch on other devices. (Also I have trouble giving up on a
problem once I start!)

Anyway, the main problem is that every single data segment (also known
as payload) in every packet has the key frame flag set which I assume
shouldn't be the case if the format conformed to the ASF spec.

Here's a dump using some print statements I added to the asf demuxer
where the stream number is the actual number rather than the converted
number used by the asfid2avid array (if that means anything to
anyone!). Stream 1 is the video stream...

packet 1: pos=9504, segs=6 size=8192 padsize=1  left=8178 flags=9 prop=93
seg 1: key:1 stream:3 seq:1 frag_size: 2, size: 2, offset:0 replic_size:214
seg 2: key:1 stream:3 seq:2 frag_size: 2, size: 2, offset:0 replic_size:214
seg 3: key:1 stream:2 seq:1 frag_size: 2020, size: 2020, offset:0
replic_size:214
seg 4: key:1 stream:1 seq:1 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 5: key:1 stream:1 seq:2 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 6: key:1 stream:1 seq:3 frag_size: 694, size: 2025, offset:0 replic_size:238
packet 2: pos=17696, segs=4 size=8192 padsize=1  left=8178 flags=9 prop=93
seg 1: key:1 stream:1 seq:3 frag_size: 1331, size: 2025, offset:694
replic_size:238
seg 2: key:1 stream:1 seq:4 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 3: key:1 stream:1 seq:5 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 4: key:1 stream:1 seq:6 frag_size: 1809, size: 2025, offset:0
replic_size:238
packet 3: pos=25888, segs=5 size=8192 padsize=1  left=8178 flags=9 prop=93
seg 1: key:1 stream:1 seq:6 frag_size: 216, size: 2025, offset:1809
replic_size:238
seg 2: key:1 stream:1 seq:7 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 3: key:1 stream:1 seq:8 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 4: key:1 stream:1 seq:9 frag_size: 2025, size: 2025, offset:0
replic_size:238
seg 5: key:1 stream:1 seq:10 frag_size: 652, size: 1151, offset:0
replic_size:238

One thing I'm uncertain about is this - I think each video segment
probably contains a single frame at most, and sometimes a frame is
split across packets. If that's true and key frames are infrequent -
maybe 1 in 15 at a guess - how come a large proportion of these
segments are 2025 bytes in size?

Regarding key frames, my guess is that the information on whether a
particular video stream segment is part of a key frame is hidden
somewhere in an undocumented place (perhaps in the replicated data of
each segment).  I could be totally wrong though cause I really don't
know much about this whole video stuff. Anyway, the main question I
have is this - is there another way to determine if a video segment is
part of a key frame in the demuxer code?

Also, the current version of asf.c doesn't attempt to read the Simple
Index in an asf file even though it knows the GUID for the object.
I've written some code to read it on demand from the seek function
(much like the avidec.c). I can submit this as a patch if anyone wants
it but it only helps a bit... when using the index to seek the lag
time between completing the seek and finding the next key frame is
perceptibly less (usually about 8 frames) than without it. I also
think you end up closer to where you expected to be in the file with
the index so it is useful up to a point.

The Simple Index consists of a series of packet numbers (and
associated packet count) at regularly spaced time intervals. The
packet number is supposed to contain the closest past key frames so I
was quite hopeful that it would be of use here.  Eg:
pktnum:0, pktct:1
pktnum:53, pktct:1
pktnum:115, pktct:1
...
pktnum:445, pktct:2

etc

My understanding of this is that you can derive the position required
by av_add_index_entry by simply multiplying pktnum by the packet
size(fixed) and adding the data offset. The timestamp is simply the
interval times the index entry number (starting at zero). I assume you
can ignore pktct. Something like this:

for (i=0;i<ict;i++){
    pktnum=get_le32(&s->pb);
    pktct=get_le16(&s->pb);

    pos=s->data_offset + asf->packet_size*(pktnum);
    index_pts=itime/10000*i;    //itime is index time interval in nanosecs

    av_add_index_entry(s->streams[stream_index], pos, index_pts,
asf->packet_size, 0, AVINDEX_KEYFRAME);
}	

Once you get that far you can easily jump to the start of a packet
near the point you wanted to go to - ie with 1/2 a second. But then
what? I've seen other code refer to the frame_offset. Should you jump
to the start of the frame or the start of the packet. Or jump to the
start of the packet and read up to the first video segment which I'm
guessing should be a key frame? Needless to say nothing I've tried has
worked and I'm out of ideas mainly because my lack of knowledge of the
general subject.

All suggestion are welcome - please help so I can put this one behind
me - or just tell me it cant be done and I'll forget about it ;-)

John

PS if you really care about dvr-ms and would like to see then play in
MPlayer natively - ie without ffmpeg I probably know enough now to do
that (apart from getting seek completely right). I'd consider doing it
but only if there was enough interest.





More information about the ffmpeg-devel mailing list