From 048ff837f7377a8ad05a2b0012eb8f2639a0a049 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sat, 25 Feb 2023 16:19:58 +0100 Subject: [PATCH] Pass AVCodecContext to frame sinks Frame consumers may need details about the frame format. --- app/src/decoder.c | 11 ++++++++--- app/src/screen.c | 5 ++++- app/src/trait/frame_sink.h | 3 ++- app/src/v4l2_sink.c | 4 +++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/src/decoder.c b/app/src/decoder.c index d750253c..46c95929 100644 --- a/app/src/decoder.c +++ b/app/src/decoder.c @@ -25,10 +25,10 @@ sc_decoder_close_sinks(struct sc_decoder *decoder) { } static bool -sc_decoder_open_sinks(struct sc_decoder *decoder) { +sc_decoder_open_sinks(struct sc_decoder *decoder, const AVCodecContext *ctx) { for (unsigned i = 0; i < decoder->sink_count; ++i) { struct sc_frame_sink *sink = decoder->sinks[i]; - if (!sink->ops->open(sink)) { + if (!sink->ops->open(sink, ctx)) { sc_decoder_close_first_sinks(decoder, i); return false; } @@ -47,6 +47,11 @@ sc_decoder_open(struct sc_decoder *decoder, const AVCodec *codec) { decoder->codec_ctx->flags |= AV_CODEC_FLAG_LOW_DELAY; + if (codec->type == AVMEDIA_TYPE_VIDEO) { + // Only YUV 4:2:0 is supported, hardcode it + decoder->codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; + } + if (avcodec_open2(decoder->codec_ctx, codec, NULL) < 0) { LOGE("Decoder '%s': could not open codec", decoder->name); avcodec_free_context(&decoder->codec_ctx); @@ -61,7 +66,7 @@ sc_decoder_open(struct sc_decoder *decoder, const AVCodec *codec) { return false; } - if (!sc_decoder_open_sinks(decoder)) { + if (!sc_decoder_open_sinks(decoder, decoder->codec_ctx)) { av_frame_free(&decoder->frame); avcodec_close(decoder->codec_ctx); avcodec_free_context(&decoder->codec_ctx); diff --git a/app/src/screen.c b/app/src/screen.c index 425ba2c3..5dd45c26 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -330,7 +330,10 @@ event_watcher(void *data, SDL_Event *event) { #endif static bool -sc_screen_frame_sink_open(struct sc_frame_sink *sink) { +sc_screen_frame_sink_open(struct sc_frame_sink *sink, + const AVCodecContext *ctx) { + assert(ctx->pix_fmt == AV_PIX_FMT_YUV420P); + struct sc_screen *screen = DOWNCAST(sink); (void) screen; #ifndef NDEBUG diff --git a/app/src/trait/frame_sink.h b/app/src/trait/frame_sink.h index 0214ab3e..30bf0d37 100644 --- a/app/src/trait/frame_sink.h +++ b/app/src/trait/frame_sink.h @@ -5,6 +5,7 @@ #include #include +#include typedef struct AVFrame AVFrame; @@ -18,7 +19,7 @@ struct sc_frame_sink { }; struct sc_frame_sink_ops { - bool (*open)(struct sc_frame_sink *sink); + bool (*open)(struct sc_frame_sink *sink, const AVCodecContext *ctx); void (*close)(struct sc_frame_sink *sink); bool (*push)(struct sc_frame_sink *sink, const AVFrame *frame); }; diff --git a/app/src/v4l2_sink.c b/app/src/v4l2_sink.c index 9a0011f2..15ca7c60 100644 --- a/app/src/v4l2_sink.c +++ b/app/src/v4l2_sink.c @@ -156,7 +156,9 @@ sc_video_buffer_on_new_frame(struct sc_video_buffer *vb, bool previous_skipped, } static bool -sc_v4l2_sink_open(struct sc_v4l2_sink *vs) { +sc_v4l2_sink_open(struct sc_v4l2_sink *vs, const AVCodecContext *ctx) { + assert(ctx->pix_fmt == AV_PIX_FMT_YUV420P); + static const struct sc_video_buffer_callbacks cbs = { .on_new_frame = sc_video_buffer_on_new_frame, };