On 4/11/2020 12:06 PM, Anton Khirnov wrote: > --- > doc/examples/demuxing_decoding.c | 177 ++++++++++++++++--------------- > 1 file changed, 91 insertions(+), 86 deletions(-) > > diff --git a/doc/examples/demuxing_decoding.c > b/doc/examples/demuxing_decoding.c > index 9bde927321..803e35d25c 100644 > --- a/doc/examples/demuxing_decoding.c > +++ b/doc/examples/demuxing_decoding.c > @@ -55,87 +55,93 @@ static AVPacket pkt; > static int video_frame_count = 0; > static int audio_frame_count = 0; > > -static int decode_packet(int *got_frame, int cached) > +static int output_video_frame(AVFrame *frame) > +{ > + if (frame->width != width || frame->height != height || > + frame->format != pix_fmt) { > + /* To handle this change, one could call av_image_alloc again and > + * decode the following frames into another rawvideo file. */ > + fprintf(stderr, "Error: Width, height and pixel format have to be " > + "constant in a rawvideo file, but the width, height or " > + "pixel format of the input video changed:\n" > + "old: width = %d, height = %d, format = %s\n" > + "new: width = %d, height = %d, format = %s\n", > + width, height, av_get_pix_fmt_name(pix_fmt), > + frame->width, frame->height, > + av_get_pix_fmt_name(frame->format)); > + return -1; > + } > + > + printf("video_frame n:%d coded_n:%d\n", > + video_frame_count++, frame->coded_picture_number); > + > + /* copy decoded frame to destination buffer: > + * this is required since rawvideo expects non aligned data */ > + av_image_copy(video_dst_data, video_dst_linesize, > + (const uint8_t **)(frame->data), frame->linesize, > + pix_fmt, width, height); > + > + /* write to rawvideo file */ > + fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); > + return 0; > +} > + > +static int output_audio_frame(AVFrame *frame) > +{ > + size_t unpadded_linesize = frame->nb_samples * > av_get_bytes_per_sample(frame->format); > + printf("audio_frame n:%d nb_samples:%d pts:%s\n", > + audio_frame_count++, frame->nb_samples, > + av_ts2timestr(frame->pts, &audio_dec_ctx->time_base)); > + > + /* Write the raw audio data samples of the first plane. This works > + * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, > + * most audio decoders output planar audio, which uses a separate > + * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). > + * In other words, this code will write only the first audio channel > + * in these cases. > + * You should use libswresample or libavfilter to convert the frame > + * to packed data. */ > + fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); > + > + return 0; > +} > + > +static int decode_packet(AVCodecContext *dec, const AVPacket *pkt) > { > int ret = 0; > - int decoded = pkt.size; > > - *got_frame = 0; > + // submit the packet to the decoder > + ret = avcodec_send_packet(dec, pkt); > + if (ret < 0) { > + fprintf(stderr, "Error submitting a packet for decoding (%s)\n", > av_err2str(ret)); > + return ret; > + } > > - if (pkt.stream_index == video_stream_idx) { > - /* decode video frame */ > - ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); > + // get all the available frames from the decoder
Instead of this, it might be better to call receive_frame() one time after each call to send_packet(), regardless of the latter consuming the packet or not. If it doesn't, then you just keep it around until at some point a call will consume it, then you can fetch the next one. I say this because if you do ret = avcodec_send_packet(pkt); av_packet_unref(pkt); if (ret < 0) return ret: do { ret = avcodec_receive_frame(frame); if (!ret) output_frame(frame): } while (!ret); You'll be draining the decoders of all the frames it may have generated, which may be detrimental in frame threading scenarios, versus something like (Untested PoC): do { ret = avcodec_send_packet(pkt); if (ret < 0) { if (ret != AVERROR(EAGAIN)) return ret; } else av_packet_unref(pkt); ret = avcodec_receive_frame(frame); if (ret < 0) { if (ret != AVERROR(EAGAIN)) return ret; } else output_frame(frame); } while (!ret || pkt->size); Which would constantly keep the decoder fed with packets as you retrieve generated frames. This is something I've noticed when writing the libdav1d decoder wrapper. I don't know if it also applies to our frame threading logic, or if it depends on the decoder used, but if it does, then the CLI would also benefit from this. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".