[FFmpeg-devel] [PATCH 1/2] examples: demuxing: do partial audio packet decoding

Stefano Sabatini stefasab at gmail.com
Sun Jul 14 11:43:46 CEST 2013


On date Saturday 2013-07-13 15:53:19 +0200, wm4 encoded:
> This assumes one audio packet is decoded one time. This is not true:
> packets can be partially decoded. Then you have to "adjust" the packet
> and pass the undecoded part of the packet to the decode function again.
> ---
>  doc/examples/demuxing.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/doc/examples/demuxing.c b/doc/examples/demuxing.c
> index 8a1b69b..1c0f1ff 100644
> --- a/doc/examples/demuxing.c
> +++ b/doc/examples/demuxing.c
> @@ -60,6 +60,7 @@ static int audio_frame_count = 0;
>  static int decode_packet(int *got_frame, int cached)
>  {
>      int ret = 0;
> +    int decoded = pkt.size;

After re-reading the docs, avcodec_decode_video2 should return the
consumed bytes as well, so we can assume that ret will contain
pkt.size after decoding.

>  
>      if (pkt.stream_index == video_stream_idx) {
>          /* decode video frame */
> @@ -91,6 +92,11 @@ static int decode_packet(int *got_frame, int cached)
>              fprintf(stderr, "Error decoding audio frame\n");
>              return ret;
>          }
> +        /* Some audio decoders decode only part of the packet, and have to be
> +         * called again with the remainder of the packet data.
> +         * Sample: fate-suite/lossless-audio/luckynight-partial.shn

> +         * Also, some decoders might over-read the packet. */
> +        decoded = FFMIN(ret, pkt.size);

What decoders? This sounds as a bug, not something to band-aid in the
application code.

Also, even in this case the external check on pkt.size > 0 should work
fine.

>  
>          if (*got_frame) {
>              printf("audio_frame%s n:%d nb_samples:%d pts:%s\n",
> @@ -121,7 +127,7 @@ static int decode_packet(int *got_frame, int cached)
>          }
>      }
>  
> -    return ret;
> +    return decoded;
>  }

>  
>  static int open_codec_context(int *stream_idx,
> @@ -293,8 +299,15 @@ int main (int argc, char **argv)
>  
>      /* read frames from the file */
>      while (av_read_frame(fmt_ctx, &pkt) >= 0) {
> -        decode_packet(&got_frame, 0);
> -        av_free_packet(&pkt);
> +        AVPacket orig_pkt = pkt;
> +        do {
> +            ret = decode_packet(&got_frame, 0);
> +            if (ret < 0)
> +                break;
> +            pkt.data += ret;
> +            pkt.size -= ret;
> +        } while (pkt.size > 0);
> +        av_free_packet(&orig_pkt);
>      }
>  
>      /* flush cached frames */

This looks good.
-- 
FFmpeg = Fantastic and Forgiving Mortal Pitiful Encoding/decoding Gorilla


More information about the ffmpeg-devel mailing list