[Libav-user] "no picture" from decoding single h264 keyframe

Camera Man i.like.privacy.too at gmail.com
Fri Apr 4 19:42:20 CEST 2014


On 04/03/2014 04:28 AM, Andrey Utkin wrote:

 > This shouldn't be RTP loss, the camera is connected directly to my PC
 > with a patchcord.

It is unlikely to be RTP loss (see below), but I've seen UDP loss even 
in direct connections (due to small buffers and other conditions), so to 
be extra sure this isn't one of the reasons, you should force a TCP session.

 > Could please somebody elaborate what exactly happens? Is above
 > approach generally broken, or it can be fixed (without decoding a lot
 > more frames)

You basically do not need to decode any more frames - an I frame can be 
decoded without any other frame. However, the ffmpeg API is optimized 
for the general use case where you continuously decode lots of frames. 
There are several causes for the video decoding not providing a picture 
immediately:

1) Stream specifies it shouldn't. Your input stream can say "we need 4 
frames decoded before the first one is shown",  in which case ffmpeg 
will decode 4 frames before returning the first one for you EVEN though 
it is independent. This is for a case of an IBBP (display, which are 
encoded as IPBB) - if you display the I, you will then have a "bubble" 
while you decode the P because you can't show it until after you've 
decoded both Bs.

This being an Axis camera, it is probably not your case - Axis cameras 
usually give a stream that doesn't specify this. But some cameras do (I 
have a Sanyo that does, for example).

2) You are using a multithreaded decode (default build does that). In 
the case, for every thread (default = 2 * cores), you will get one frame 
delay between input and output. This is because decoding is handed off 
to a thread, and control returns to you immediately. So only when you 
feed some more frames, you will get the first frame back.

This is more likely the cause for what you are seeing. You can disable 
multithreaded decode by setting the codec context's "thread_type" field 
to 0 after setting up the stream but before calling avcodec_open2().

In both cases, even if you do not turn multithreaded decoding off, you 
most likely do not need to feed in more frames - you can keep feeding 
NULL packets until you do get the decoded images - but note that as soon 
as you feed the first NULL packet, you imply the stream has ended - and 
you cannot keep decoding it. You will need to reset all buffers and 
restart decoding if you need any other picture decoded.

The important things to understand is that because of reordering, some 
codecs (and h264 is a prime example) do not have a "packet in -> picture 
out" relationship in the ffmpeg API. It would have been clearer if 
instead of decode_video2(), you had two routines: 
"feed_video_packet_to_decoder()", and 
"give_me_a_picture_if_its_ready_or_tell_me_if_not()" - but they are 
fused into "decode_video2()" (for historical reasons, I would guess), so 
you experience the behaviour that you do.




More information about the Libav-user mailing list