diff --git a/app/src/decoder.c b/app/src/decoder.c index 7da959c6..dd2a8a1e 100644 --- a/app/src/decoder.c +++ b/app/src/decoder.c @@ -30,11 +30,19 @@ decoder_open(struct decoder *decoder, const AVCodec *codec) { return false; } + decoder->frame = av_frame_alloc(); + if (!decoder->frame) { + avcodec_close(decoder->codec_ctx); + avcodec_free_context(&decoder->codec_ctx); + return false; + } + return true; } void decoder_close(struct decoder *decoder) { + av_frame_free(&decoder->frame); avcodec_close(decoder->codec_ctx); avcodec_free_context(&decoder->codec_ctx); } @@ -49,11 +57,11 @@ decoder_push(struct decoder *decoder, const AVPacket *packet) { LOGE("Could not send video packet: %d", ret); return false; } - ret = avcodec_receive_frame(decoder->codec_ctx, - decoder->video_buffer->producer_frame); + ret = avcodec_receive_frame(decoder->codec_ctx, decoder->frame); if (!ret) { // a frame was received - video_buffer_producer_offer_frame(decoder->video_buffer); + video_buffer_producer_offer_frame(decoder->video_buffer, + &decoder->frame); } else if (ret != AVERROR(EAGAIN)) { LOGE("Could not receive video frame: %d", ret); return false; @@ -61,7 +69,7 @@ decoder_push(struct decoder *decoder, const AVPacket *packet) { #else int got_picture; int len = avcodec_decode_video2(decoder->codec_ctx, - decoder->video_buffer->decoding_frame, + decoder->frame, &got_picture, packet); if (len < 0) { diff --git a/app/src/decoder.h b/app/src/decoder.h index bbd7a9a7..69e06828 100644 --- a/app/src/decoder.h +++ b/app/src/decoder.h @@ -12,6 +12,7 @@ struct decoder { struct video_buffer *video_buffer; AVCodecContext *codec_ctx; + AVFrame *frame; }; void diff --git a/app/src/video_buffer.c b/app/src/video_buffer.c index 94619840..d22e96b9 100644 --- a/app/src/video_buffer.c +++ b/app/src/video_buffer.c @@ -8,24 +8,19 @@ bool video_buffer_init(struct video_buffer *vb, bool wait_consumer) { - vb->producer_frame = av_frame_alloc(); - if (!vb->producer_frame) { - goto error_0; - } - vb->pending_frame = av_frame_alloc(); if (!vb->pending_frame) { - goto error_1; + goto error_0; } vb->consumer_frame = av_frame_alloc(); if (!vb->consumer_frame) { - goto error_2; + goto error_1; } bool ok = sc_mutex_init(&vb->mutex); if (!ok) { - goto error_3; + goto error_2; } vb->wait_consumer = wait_consumer; @@ -49,12 +44,10 @@ video_buffer_init(struct video_buffer *vb, bool wait_consumer) { return true; -error_3: - av_frame_free(&vb->consumer_frame); error_2: - av_frame_free(&vb->pending_frame); + av_frame_free(&vb->consumer_frame); error_1: - av_frame_free(&vb->producer_frame); + av_frame_free(&vb->pending_frame); error_0: return false; } @@ -67,7 +60,6 @@ video_buffer_destroy(struct video_buffer *vb) { sc_mutex_destroy(&vb->mutex); av_frame_free(&vb->consumer_frame); av_frame_free(&vb->pending_frame); - av_frame_free(&vb->producer_frame); } static inline void @@ -89,7 +81,7 @@ video_buffer_set_consumer_callbacks(struct video_buffer *vb, } void -video_buffer_producer_offer_frame(struct video_buffer *vb) { +video_buffer_producer_offer_frame(struct video_buffer *vb, AVFrame **pframe) { assert(vb->cbs); sc_mutex_lock(&vb->mutex); @@ -101,7 +93,7 @@ video_buffer_producer_offer_frame(struct video_buffer *vb) { } av_frame_unref(vb->pending_frame); - swap_frames(&vb->producer_frame, &vb->pending_frame); + swap_frames(pframe, &vb->pending_frame); bool skipped = !vb->pending_frame_consumed; vb->pending_frame_consumed = false; diff --git a/app/src/video_buffer.h b/app/src/video_buffer.h index 4d11e3ab..e7efdfbf 100644 --- a/app/src/video_buffer.h +++ b/app/src/video_buffer.h @@ -29,7 +29,6 @@ typedef struct AVFrame AVFrame; */ struct video_buffer { - AVFrame *producer_frame; AVFrame *pending_frame; AVFrame *consumer_frame; @@ -67,8 +66,9 @@ video_buffer_set_consumer_callbacks(struct video_buffer *vb, void *cbs_userdata); // set the producer frame as ready for consuming +// the produced frame is exchanged with an unused allocated frame void -video_buffer_producer_offer_frame(struct video_buffer *vb); +video_buffer_producer_offer_frame(struct video_buffer *vb, AVFrame **pframe); // mark the consumer frame as consumed and return it // the frame is valid until the next call to this function