From e2f0bb34d7e3474b10aafe71308236fedd91ee73 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 23 Aug 2023 16:40:21 +0200 Subject: [PATCH] lavd video: removed parser This effectively reverts recent commit d70e2fb3 (from 15th Aug). The use of parser seems to be a problem for UG workflow, in the end - the point is that it may cache a packet until arival of next packet (commit 6e9a4142), so in that commit, as a solution flushing with EOF was added. However, it seems to produce problems with simple (but not with H.264 parser): ``` uv -d gl -t testcard -c libavcodec:encoder=libx265 ``` because the parser seems to be confused when parsing frames after EOF so for the subsequent frames it consumes 1 byte producing 1 byte output. This is mostly harmless (it is actually '\0', part of the start code), but it produces errors: ``` [lavc hevc @ 0x68216c0055c0] missing picture in access unit with size 1 ``` Possible solution would be to re-create the parser for every frame (sic!) but it is unclear the overhead (which applies also to parsing the frames, anyways). Anyways, as piggy-backed frames should not occur since the commit c57f2fc5, it is perhaps best to remove this stuff altogether. --- src/video_decompress/libavcodec.c | 91 ++++++++----------------------- 1 file changed, 24 insertions(+), 67 deletions(-) diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index 3e61882db..903601b83 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -69,11 +69,10 @@ #define MOD_NAME "[lavd] " struct state_libavcodec_decompress { - AVCodecContext *codec_ctx; - AVCodecParserContext *parser; - AVFrame *frame; - AVFrame *tmp_frame; - AVPacket *pkt; + AVCodecContext *codec_ctx; + AVFrame *frame; + AVFrame *tmp_frame; + AVPacket *pkt; struct video_desc desc; int pitch; @@ -105,8 +104,6 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const en static void deconfigure(struct state_libavcodec_decompress *s) { - av_parser_close(s->parser); - s->parser = NULL; if(s->codec_ctx) { lavd_flush(s->codec_ctx); avcodec_free_context(&s->codec_ctx); @@ -352,10 +349,6 @@ static bool configure_with(struct state_libavcodec_decompress *s, if (dec->codec_callback) { dec->codec_callback(); } - s->parser = av_parser_init(dec->avcodec_id); - if (s->parser == NULL) { - log_msg(LOG_LEVEL_WARNING, MOD_NAME "Cannot create parser!\n"); - } // priority list of decoders that can be used for the codec const AVCodec *usable_decoders[DEC_LEN] = { NULL }; @@ -977,60 +970,28 @@ static bool decode_frame(struct state_libavcodec_decompress *s, unsigned char *src, int src_len) { - int ret = 0; - bool frame_decoded = false; - const char *dec_err_pref = MOD_NAME; - while (true) { - const bool eof = src_len == 0; - if (s->parser == NULL) { - s->pkt->data = src; - s->pkt->size = src_len; - ret = src_len; - } else { - ret = av_parser_parse2(s->parser, s->codec_ctx, - &s->pkt->data, &s->pkt->size, - src, src_len, AV_NOPTS_VALUE, - AV_NOPTS_VALUE, 0); - if (ret < 0) { - dec_err_pref = MOD_NAME "av_parser_parse2 - "; - break; - } - } - src += ret; - src_len -= ret; - if (s->pkt->size == 0) { - if (eof) { - break; - } - continue; - } - ret = avcodec_send_packet(s->codec_ctx, s->pkt); - if (ret != 0 && ret != AVERROR(EAGAIN)) { - dec_err_pref = MOD_NAME "send - "; - break; - } - // we output to tmp_frame because even if receive fails, - // it overrides previous potentially valid frame - while ((ret = avcodec_receive_frame(s->codec_ctx, - s->tmp_frame)) == 0) { - if (frame_decoded) { - log_msg(LOG_LEVEL_WARNING, MOD_NAME - "Multiple frames decoded at once!\n"); - } - frame_decoded = true; - SWAP_PTR(s->frame, s->tmp_frame); - } - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { - continue; + bool frame_decoded = false; + s->pkt->data = src; + s->pkt->size = src_len; + int ret = avcodec_send_packet(s->codec_ctx, s->pkt); + if (ret != 0 && ret != AVERROR(EAGAIN)) { + handle_lavd_error(MOD_NAME "send - ", s, ret); + return false; + } + // we output to tmp_frame because even if receive fails, + // it overrides previous potentially valid frame + while ((ret = avcodec_receive_frame(s->codec_ctx, s->tmp_frame)) == 0) { + if (frame_decoded) { + log_msg(LOG_LEVEL_WARNING, + MOD_NAME "Multiple frames decoded at once!\n"); } + frame_decoded = true; + SWAP_PTR(s->frame, s->tmp_frame); + } + if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { handle_lavd_error(MOD_NAME "recv - ", s, ret); } - - if (frame_decoded) { - return true; - } - handle_lavd_error(dec_err_pref, s, ret); - return false; + return frame_decoded; } static decompress_status libavcodec_decompress(void *state, unsigned char *dst, unsigned char *src, @@ -1065,11 +1026,7 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst, time_ns_t t0 = get_time_in_ns(); if (!decode_frame(s, src, src_len)) { - if (s->parser) { - log_msg(LOG_LEVEL_DEBUG, - MOD_NAME "Parsed %c frame but not decoded.\n", - av_get_picture_type_char(s->parser->pict_type)); - } + log_msg(LOG_LEVEL_DEBUG, MOD_NAME "No frame was decoded!\n"); return DECODER_NO_FRAME; } s->consecutive_failed_decodes = 0;