[Kdenlive-devel] Solved: AVCHD camcorder support

Ivan Schreter schreter at gmx.net
Thu Feb 12 21:11:21 UTC 2009


Dan Dennedy wrote:
> I hope you realize by now that this is common - both the treatment and
> your reaction / perception. It's probably best to think of Michael &Co
> as a gatekeeper to the holy land. Unfortunately, sometimes I think
> they have that perception of themselves as well. ;-) However, the fact
> that he reads your patches and responds is actually a good sign.
>   
Yes, that's why I still bear with it :-)

> [...]
>> OTOH, MLT has also some bugs in libavformat handler, most prominently
>> off-by-two frames for MPEG-2 and H.264 (and possibly other codecs) as
>> well as wrong usage of av_read_frame(), which can be attributed to
>> deficient documentation. If correct solution for AVCHD is built into
>> FFmpeg, MLT has to be fixed as well.
>>     
>
> I will take a look at this. Have you noticed this only with transport
> stream or with program stream and mp4 or mov as well? If you have some
> diff in your working copy, not matter how ugly, please send it so I
> can start looking at what you changed and why.
>   
There is one big problem: av_read_frame() doesn't read a video frame as 
one would expect for video streams, but a demuxer frame. This means, for 
H.264 (e.g., AVCHD) videos, you'd need to make two av_read_frame() calls 
before getting the next picture for field-coded H.264 streams (which 
seems to be the case at least for 1080i videos on Panasonic, Sony and 
Canon camcorders). This also isn't the biggest problem, since MLT does 
seem to loop, but I believe the termination condition is possibly not 
sufficient. Similarly, there are video formats, where one demuxer frame 
might contain more than one video frame. I.e., you'd probably need to 
feed avcodec_decode_frame() with NULL buffers to get the rest of the 
pictures in one demuxer frame.

For now, stock FFmpeg doesn't return timestamps for field-coded videos 
properly. Timestamps of frame-coded progressive H.264 (sort of) work. 
For field-coded videos, the first field of the frame would have DTS/PTS 
as usual, the second one either the same or offset by 1/2 duration. This 
doesn't work as of today and computation of proper timestamps is quite 
an obnoxious thing. One of my patches simply joined the two fields in 
parser, thus returning a buffer with one video frame and thus 
alleviating the problem.

Seeking in MPEG-TS stream (as produced by the camcorder) doesn't work as 
well in FFmpeg, since frame positions in-stream are determined 
incorrectly in general and in MPEG-TS in particular. Further, MPEG-TS 
seeking doesn't look for key frame, it takes just some frame with 
timestamp present. So decoding isn't restarted correctly. I've posted a 
series of patches for review a week ago, with no answer from MPEG-TS 
maintainer so far in spite of 2 pings and his activity on other topics...

I didn't test with program stream and/or mp4. I wanted to test with mov, 
but since remuxing to mov failed (video can't be read at all from 
resuling mov file), I cannot say much.

I didn't study the MLT code thoroughly yet, so I don't know what/how to 
fix and don't have a patch yet. I noticed the following, though:

1) The aforementioned problem with av_read_frame().

2) Seeking seeks 1 second before actually needed position. I suppose, 
this is a workaround for aforementioned MPEG-TS seeking bug (and 
possibly bugs in other formats), which simply starts at some frame, not 
necessarily a key frame. This one second won't be needed after MPEG-TS 
seeking is fixed. For now, just GOP time should suffice as workaround 
(which is, granted, close to 1 second anyway :-).

H.264 complicates things further, by having so-called recovery points 
with convergence duration. I.e., you don't have a single frame where to 
start from, you have a start frame and count of frames to decode until 
the output converges to what it would be when decoding from start of the 
stream. This should be addressed in FFmpeg seeking, though, by 
positioning the stream at a keyframe with distance >= convergence 
duration. Thus, decoding until requested PTS would converge the stream. 
However, handling of recovery point is not yet in FFmpeg (just 
partially). Fortunately, all H.264 videos I've seen so far have recovery 
count set to 0, which effectively makes frames with recovery count 0 
unconditional keyframes. So we don't have to wait for full solution 
there just to decode AVCHD from camcorders.

3) The off-by-two stems from using DTS instead of PTS for timestamps. 
After stream start or seek, a key frame is read with PTS = DTS + delay, 
followed by B frames as needed with PTS=DTS. So first few 
avcodec_decode_video() calls won't return a picture. The first picture 
returned has PTS of the key frame. MLT seems to use DTS of last-read 
frame instead (and generally something seems to go wrong there). So if I 
open a file from my camcorder, first frame is displayed. Single-stepping 
will then duplicate it for next 2 frames (delay) and only then start 
displaying further frames. After a seek, single stepping does work from 
beginning, but it's offset by delay (since DTS is used instead of PTS).

I would wish FFmpeg would pair the resulting decoded picture with PTS of 
av_read_frame, so that this is clear. There actually is a field for 
that, but it doesn't work correctly. So the only way to get proper 
timestamps is to read frames at the beginning / after the seek until the 
first picture is decoded. Then you know you are at PTS of the key frame 
at start of the stream or after a seek (PTS of first frame read via 
av_rad_frame). Then, for next frame, simply read frames via 
av_read_frame() & decode until next picture is decoded. Again, you know 
you are at PTS of the last frame + duration. Of course, if you have a 
broken stream with gaps, this won't work (one can resync, though, by 
computing the delay from a key frame and then correct PTS of the picture 
after so many video frames are read & decoded to the PTS of that last 
key frame).

I hope this clarifies the things a bit...

Regards,

Ivan

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kdenlive/attachments/20090212/7df29997/attachment.html>


More information about the Kdenlive mailing list