diff --git a/app/src/decoder.c b/app/src/decoder.c index 99119aa6..7d5923b0 100644 --- a/app/src/decoder.c +++ b/app/src/decoder.c @@ -14,7 +14,7 @@ // set the decoded frame as ready for rendering, and notify static void push_frame(struct decoder *decoder) { - video_buffer_producer_offer_frame(decoder->video_buffer); + video_buffer_producer_offer_frame(decoder->video_buffer, &decoder->frame); } void @@ -36,11 +36,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); } @@ -55,8 +63,7 @@ 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 push_frame(decoder); @@ -67,7 +74,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 27afcd8e..57cfd3af 100644 --- a/app/src/decoder.h +++ b/app/src/decoder.h @@ -11,6 +11,7 @@ struct video_buffer; 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 fc5e7c93..e871a987 100644 --- a/app/src/video_buffer.c +++ b/app/src/video_buffer.c @@ -10,24 +10,19 @@ bool video_buffer_init(struct video_buffer *vb, bool wait_consumer, const struct video_buffer_callbacks *cbs, void *cbs_userdata) { - 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; @@ -54,12 +49,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; } @@ -72,7 +65,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 @@ -83,7 +75,7 @@ swap_frames(AVFrame **lhs, AVFrame **rhs) { } void -video_buffer_producer_offer_frame(struct video_buffer *vb) { +video_buffer_producer_offer_frame(struct video_buffer *vb, AVFrame **pframe) { sc_mutex_lock(&vb->mutex); if (vb->wait_consumer) { // wait for the current (expired) frame to be consumed @@ -93,7 +85,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; if (skipped) { diff --git a/app/src/video_buffer.h b/app/src/video_buffer.h index 96456f32..4741a47b 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; @@ -60,8 +59,9 @@ void video_buffer_destroy(struct video_buffer *vb); // 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