diff --git a/src/libavcodec/from_lavc_vid_conv.c b/src/libavcodec/from_lavc_vid_conv.c index d5758e193..2fa907f9e 100644 --- a/src/libavcodec/from_lavc_vid_conv.c +++ b/src/libavcodec/from_lavc_vid_conv.c @@ -4,7 +4,7 @@ * @author Martin Piatka <445597@mail.muni.cz> */ /* - * Copyright (c) 2013-2023 CESNET, z. s. p. o. + * Copyright (c) 2013-2024 CESNET, z. s. p. o. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,12 +44,6 @@ * Some conversions to RGBA ignore RGB-shifts - either fix that or deprecate RGB-shifts */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#include "config_unix.h" -#include "config_win32.h" -#endif // HAVE_CONFIG_H - #include #include #include @@ -2181,13 +2175,12 @@ static void vuyx_to_y416(char * __restrict dst_buffer, AVFrame * __restrict in_f typedef void av_to_uv_convert_f(char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, const int * __restrict rgb_shift); typedef av_to_uv_convert_f *av_to_uv_convert_fp; -struct av_to_uv_convert_state_priv { +struct av_to_uv_convert_state { av_to_uv_convert_fp convert; codec_t src_pixfmt; codec_t dst_pixfmt; decoder_t dec; }; -_Static_assert(sizeof(struct av_to_uv_convert_state_priv) <= sizeof ((struct av_to_uv_convert_state *) 0)->priv_data, "increase av_to_uv_convert_state::priv_data size"); struct av_to_uv_conversion { enum AVPixelFormat av_codec; @@ -2325,18 +2318,18 @@ static const struct av_to_uv_conversion av_to_uv_conversions[] = { #define AV_TO_UV_CONVERSION_COUNT (sizeof av_to_uv_conversions / sizeof av_to_uv_conversions[0]) static const struct av_to_uv_conversion *av_to_uv_conversions_end = av_to_uv_conversions + AV_TO_UV_CONVERSION_COUNT; -static void set_decoder_mapped_to_uv(av_to_uv_convert_t *ret, decoder_t dec, - codec_t dst_pixfmt) { - struct av_to_uv_convert_state_priv *priv = (void *) ret->priv_data; - priv->dec = dec; - priv->dst_pixfmt = dst_pixfmt; - ret->valid = true; +static void +set_decoder_mapped_to_uv(av_to_uv_convert_t *s, decoder_t dec, + codec_t dst_pixfmt) +{ + s->dec = dec; + s->dst_pixfmt = dst_pixfmt; } -static void set_decoder_memcpy(av_to_uv_convert_t *ret, codec_t color_spec) { - struct av_to_uv_convert_state_priv *priv = (void *) ret->priv_data; - priv->dst_pixfmt = color_spec; - ret->valid = true; +static void +set_decoder_memcpy(av_to_uv_convert_t *s, codec_t color_spec) +{ + s->dst_pixfmt = color_spec; } static QSORT_S_COMP_DEFINE(compare_convs, a, b, orig_c) { @@ -2376,22 +2369,33 @@ static decoder_t get_av_and_uv_conversion(enum AVPixelFormat av_codec, codec_t u return NULL; } -av_to_uv_convert_t get_av_to_uv_conversion(int av_codec, codec_t uv_codec) { - av_to_uv_convert_t ret = { .valid = false }; - struct av_to_uv_convert_state_priv *priv = (void *) ret.priv_data; +void +av_to_uv_conversion_destroy(av_to_uv_convert_t **s) +{ + if (s == NULL || *s == NULL) { + return; + } + free(*s); + *s = NULL; +} + +av_to_uv_convert_t *get_av_to_uv_conversion(int av_codec, codec_t uv_codec) { + av_to_uv_convert_t *ret = calloc(1, sizeof *ret); codec_t mapped_pix_fmt = get_av_to_ug_pixfmt(av_codec); if (mapped_pix_fmt == uv_codec) { if (codec_is_planar(uv_codec)) { log_msg(LOG_LEVEL_ERROR, "Planar pixfmts not support here, please report a bug!\n"); - } else { - set_decoder_memcpy(&ret, uv_codec); + free(ret); + return NULL; } + set_decoder_memcpy(ret, uv_codec); return ret; - } else if (mapped_pix_fmt) { + } + if (mapped_pix_fmt != VC_NONE) { decoder_t dec = get_decoder_from_to(mapped_pix_fmt, uv_codec); if (dec) { - set_decoder_mapped_to_uv(&ret, dec, uv_codec); + set_decoder_mapped_to_uv(ret, dec, uv_codec); return ret; } } @@ -2400,25 +2404,24 @@ av_to_uv_convert_t get_av_to_uv_conversion(int av_codec, codec_t uv_codec) { conversions < av_to_uv_conversions_end; conversions++) { if (conversions->av_codec == av_codec && conversions->uv_codec == uv_codec) { - priv->convert = conversions->convert; - ret.valid = true; + ret->convert = conversions->convert; watch_pixfmt_degrade(MOD_NAME, av_pixfmt_get_desc(av_codec), get_pixfmt_desc(uv_codec)); return ret; } } av_to_uv_convert_fp av_convert = NULL; - codec_t intermediate; + codec_t intermediate = VC_NONE; decoder_t dec = get_av_and_uv_conversion(av_codec, uv_codec, &intermediate, &av_convert); if (!dec) { - return ret; + free(ret); + return NULL; } - priv->dec = dec; - priv->convert = av_convert; - priv->src_pixfmt = intermediate; - priv->dst_pixfmt = uv_codec; - ret.valid = true; + ret->dec = dec; + ret->convert = av_convert; + ret->src_pixfmt = intermediate; + ret->dst_pixfmt = uv_codec; watch_pixfmt_degrade(MOD_NAME, av_pixfmt_get_desc(av_codec), get_pixfmt_desc(intermediate)); watch_pixfmt_degrade(MOD_NAME, get_pixfmt_desc(intermediate), get_pixfmt_desc(uv_codec)); @@ -2497,11 +2500,13 @@ enum AVPixelFormat lavd_get_av_to_ug_codec(const enum AVPixelFormat *fmt, codec_ return get_ug_codec_to_av(fmt, &c, use_hwaccel); } -enum AVPixelFormat pick_av_convertible_to_ug(codec_t color_spec, av_to_uv_convert_t *av_conv) { - av_conv->valid = false; +enum AVPixelFormat +pick_av_convertible_to_ug(codec_t color_spec, av_to_uv_convert_t **av_conv) +{ + *av_conv = calloc(1, sizeof **av_conv); if (get_ug_to_av_pixfmt(color_spec) != AV_PIX_FMT_NONE) { - set_decoder_memcpy(av_conv, color_spec); + set_decoder_memcpy(*av_conv, color_spec); return get_ug_to_av_pixfmt(color_spec); } @@ -2509,58 +2514,66 @@ enum AVPixelFormat pick_av_convertible_to_ug(codec_t color_spec, av_to_uv_conver decoder_t dec; if (out_desc.rgb) { if (out_desc.depth > 8 && (dec = get_decoder_from_to(RG48, color_spec))) { - set_decoder_mapped_to_uv(av_conv, dec, color_spec); + set_decoder_mapped_to_uv(*av_conv, dec, color_spec); return AV_PIX_FMT_RGB48LE; } else if ((dec = get_decoder_from_to(RGB, color_spec))) { - set_decoder_mapped_to_uv(av_conv, dec, color_spec); + set_decoder_mapped_to_uv(*av_conv, dec, color_spec); return AV_PIX_FMT_RGB24; } } #if XV3X_PRESENT if (out_desc.depth > 8 && (dec = get_decoder_from_to(Y416, color_spec))) { - set_decoder_mapped_to_uv(av_conv, dec, color_spec); + set_decoder_mapped_to_uv(*av_conv, dec, color_spec); return AV_PIX_FMT_XV36; } #endif if ((dec = get_decoder_from_to(UYVY, color_spec))) { - set_decoder_mapped_to_uv(av_conv, dec, color_spec); + set_decoder_mapped_to_uv(*av_conv, dec, color_spec); return AV_PIX_FMT_UYVY422; } for (const struct av_to_uv_conversion *c = av_to_uv_conversions; c < av_to_uv_conversions_end; c++) { if (c->uv_codec == color_spec) { // pick any (first usable) - av_conv->valid = true; - struct av_to_uv_convert_state_priv *priv = (void *) av_conv->priv_data; - memset(priv, 0, sizeof *priv); - priv->convert = c->convert; + memset(*av_conv, 0, sizeof **av_conv); + (*av_conv)->convert = c->convert; return c->av_codec; } } + free(*av_conv); + *av_conv = NULL; return AV_PIX_FMT_NONE; } -void av_to_uv_convert(const av_to_uv_convert_t *state, char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, const int * __restrict rgb_shift) { - const struct av_to_uv_convert_state_priv *priv = (const void *) state->priv_data; +void +av_to_uv_convert(const av_to_uv_convert_t *s, char *__restrict dst_buffer, + AVFrame *__restrict in_frame, int width, int height, int pitch, + const int *__restrict rgb_shift) +{ unsigned char *dec_input = in_frame->data[0]; size_t src_linesize = in_frame->linesize[0]; unsigned char *tmp = NULL; - if (priv->convert) { + if (s->convert) { DEBUG_TIMER_START(lavd_av_to_uv); - if (!priv->dec) { - priv->convert(dst_buffer, in_frame, width, height, pitch, rgb_shift); + if (!s->dec) { + s->convert(dst_buffer, in_frame, width, height, pitch, rgb_shift); DEBUG_TIMER_STOP(lavd_av_to_uv); return; } - src_linesize = vc_get_linesize(width, priv->src_pixfmt); - dec_input = tmp = malloc(vc_get_datalen(width, height, priv->src_pixfmt) + MAX_PADDING); - int default_rgb_shift[] = { DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT }; - priv->convert((char *) dec_input, in_frame, width, height, src_linesize, default_rgb_shift); + src_linesize = vc_get_linesize(width, s->src_pixfmt); + dec_input = tmp = malloc( + vc_get_datalen(width, height, s->src_pixfmt) + MAX_PADDING); + int default_rgb_shift[] = { DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, + DEFAULT_B_SHIFT }; + s->convert((char *) dec_input, in_frame, width, height, + src_linesize, default_rgb_shift); DEBUG_TIMER_STOP(lavd_av_to_uv); } - if (priv->dec) { + if (s->dec) { DEBUG_TIMER_START(lavd_dec); - int dst_size = vc_get_size(width, priv->dst_pixfmt); + int dst_size = vc_get_size(width, s->dst_pixfmt); for (ptrdiff_t i = 0; i < height; ++i) { - priv->dec((unsigned char *) dst_buffer + i * pitch, dec_input + i * src_linesize, dst_size, rgb_shift[0], rgb_shift[1], rgb_shift[2]); + s->dec((unsigned char *) dst_buffer + i * pitch, + dec_input + i * src_linesize, dst_size, + rgb_shift[0], rgb_shift[1], rgb_shift[2]); } DEBUG_TIMER_STOP(lavd_dec); free(tmp); @@ -2568,7 +2581,7 @@ void av_to_uv_convert(const av_to_uv_convert_t *state, char * __restrict dst_buf } // memcpy only - int linesize = vc_get_linesize(width, priv->dst_pixfmt); + int linesize = vc_get_linesize(width, s->dst_pixfmt); for (ptrdiff_t i = 0; i < height; ++i) { memcpy(dst_buffer + i * pitch, in_frame->data[0] + i * in_frame->linesize[0], linesize); } diff --git a/src/libavcodec/from_lavc_vid_conv.h b/src/libavcodec/from_lavc_vid_conv.h index 4bfcb280a..9e185f3fa 100644 --- a/src/libavcodec/from_lavc_vid_conv.h +++ b/src/libavcodec/from_lavc_vid_conv.h @@ -44,7 +44,6 @@ #include "libavcodec/lavc_common.h" #ifndef __cplusplus -#include #include #endif @@ -53,18 +52,16 @@ extern "C" { #endif struct av_to_uv_convert_state; +typedef struct av_to_uv_convert_state av_to_uv_convert_t; -typedef struct av_to_uv_convert_state { - alignas(8) char priv_data[24]; - bool valid; -} av_to_uv_convert_t; +av_to_uv_convert_t *get_av_to_uv_conversion(int av_codec, codec_t uv_codec); +void av_to_uv_convert(const av_to_uv_convert_t *s, char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, const int * __restrict rgb_shift); +void av_to_uv_conversion_destroy(av_to_uv_convert_t **); -void av_to_uv_convert(const av_to_uv_convert_t *state, char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, const int * __restrict rgb_shift); - -av_to_uv_convert_t get_av_to_uv_conversion(int av_codec, codec_t uv_codec); codec_t get_best_ug_codec_to_av(const enum AVPixelFormat *fmt, bool use_hwaccel); enum AVPixelFormat lavd_get_av_to_ug_codec(const enum AVPixelFormat *fmt, codec_t c, bool use_hwaccel); -enum AVPixelFormat pick_av_convertible_to_ug(codec_t color_spec, av_to_uv_convert_t *av_conv); +enum AVPixelFormat pick_av_convertible_to_ug(codec_t color_spec, + av_to_uv_convert_t **av_conv); #ifdef __cplusplus } diff --git a/src/video_capture/file.c b/src/video_capture/file.c index 3e10a869b..cde910168 100644 --- a/src/video_capture/file.c +++ b/src/video_capture/file.c @@ -103,7 +103,7 @@ struct vidcap_state_lavf_decoder { int thread_type; struct SwsContext *sws_ctx; - av_to_uv_convert_t conv_uv; + av_to_uv_convert_t *conv_uv; bool failed; bool loop; @@ -200,6 +200,8 @@ static void vidcap_file_common_cleanup(struct vidcap_state_lavf_decoder *s) { avformat_close_input(&s->fmt_ctx); } + av_to_uv_conversion_destroy(&s->conv_uv); + flush_captured_data(s); ring_buffer_destroy(s->audio_data); @@ -422,9 +424,9 @@ static struct video_frame *process_video_pkt(struct vidcap_state_lavf_decoder *s int video_dst_linesize[4] = { vc_get_linesize(out->tiles[0].width, out->color_spec)}; uint8_t *dst[4] = {(uint8_t *)out->tiles[0].data}; - if (s->conv_uv.valid) { + if (s->conv_uv) { int rgb_shift[] = DEFAULT_RGB_SHIFT_INIT; - av_to_uv_convert(&s->conv_uv, out->tiles[0].data, frame, + av_to_uv_convert(s->conv_uv, out->tiles[0].data, frame, out->tiles[0].width, out->tiles[0].height, video_dst_linesize[0], rgb_shift); } else { @@ -695,7 +697,7 @@ static bool setup_video(struct vidcap_state_lavf_decoder *s) { } s->conv_uv = get_av_to_uv_conversion(s->vid_ctx->pix_fmt, s->video_desc.color_spec); - if (s->conv_uv.valid) { + if (s->conv_uv) { return true; } // else swscale needed diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index c08400b28..a26677bfc 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -3,7 +3,7 @@ * @author Martin Pulec */ /* - * Copyright (c) 2013-2023 CESNET, z. s. p. o. + * Copyright (c) 2013-2024 CESNET, z. s. p. o. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -83,7 +83,7 @@ struct state_libavcodec_decompress { int max_compressed_len; codec_t out_codec; struct { - av_to_uv_convert_t convert; + av_to_uv_convert_t *convert; enum AVPixelFormat convert_in; }; bool block_accel[HWACCEL_COUNT]; @@ -109,6 +109,8 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const en static void deconfigure(struct state_libavcodec_decompress *s) { + av_to_uv_conversion_destroy(&s->convert); + if(s->codec_ctx) { lavd_flush(s->codec_ctx); avcodec_free_context(&s->codec_ctx); @@ -818,8 +820,9 @@ static _Bool reconfigure_convert_if_needed(struct state_libavcodec_decompress *s if (s->convert_in == av_codec) { return 1; } + av_to_uv_conversion_destroy(&s->convert); s->convert = get_av_to_uv_conversion(av_codec, out_codec); - if (s->convert.valid) { + if (s->convert != NULL) { s->convert_in = av_codec; return 1; } @@ -862,9 +865,12 @@ static _Bool reconfigure_convert_if_needed(struct state_libavcodec_decompress *s * @param width frame width * @param height frame height */ -static void change_pixfmt(AVFrame *frame, unsigned char *dst, const av_to_uv_convert_t *convert, - codec_t out_codec, int width, int height, - int pitch, int rgb_shift[static restrict 3], struct state_libavcodec_decompress_sws *sws) { +static void +change_pixfmt(AVFrame *frame, unsigned char *dst, av_to_uv_convert_t *convert, + codec_t out_codec, int width, int height, int pitch, + int rgb_shift[static restrict 3], + struct state_libavcodec_decompress_sws *sws) +{ debug_file_dump("lavd-avframe", serialize_video_avframe, frame); if (!sws->ctx) { @@ -1092,8 +1098,9 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst, if (!reconfigure_convert_if_needed(s, s->frame->format, s->out_codec, s->desc.width, s->desc.height)) { return DECODER_UNSUPP_PIXFMT; } - change_pixfmt(s->frame, dst, &s->convert, s->out_codec, s->desc.width, - s->desc.height, s->pitch, s->rgb_shift, &s->sws); + change_pixfmt(s->frame, dst, s->convert, s->out_codec, + s->desc.width, s->desc.height, s->pitch, + s->rgb_shift, &s->sws); } time_ns_t t2 = get_time_in_ns(); log_msg(LOG_LEVEL_DEBUG, MOD_NAME "Decompressing %c frame took %f ms, pixfmt change %f ms.\n", av_get_picture_type_char(s->frame->pict_type), diff --git a/test/ff_codec_conversions_test.cpp b/test/ff_codec_conversions_test.cpp index 571d09500..c0c25a087 100644 --- a/test/ff_codec_conversions_test.cpp +++ b/test/ff_codec_conversions_test.cpp @@ -66,14 +66,15 @@ int ff_codec_conversions_test_yuv444pXXle_from_to_r10k() struct to_lavc_vid_conv *from_conv = to_lavc_vid_conv_init(R10k, width, height, avfmt, 1); auto to_conv = get_av_to_uv_conversion(avfmt, R10k); - assert(to_conv.valid && from_conv != nullptr); + assert(to_conv != nullptr && from_conv != nullptr); TIMER(t0); AVFrame *converted = to_lavc_vid_conv(from_conv, (char *) r10k_buf.data()); TIMER(t1); - av_to_uv_convert(&to_conv, reinterpret_cast(r10k_buf.data()), converted, width, height, vc_get_linesize(width, R10k), nullptr); + av_to_uv_convert(to_conv, reinterpret_cast(r10k_buf.data()), converted, width, height, vc_get_linesize(width, R10k), nullptr); TIMER(t2); to_lavc_vid_conv_destroy(&from_conv); + av_to_uv_conversion_destroy(&to_conv); if (getenv("PERF") != nullptr) { cout << "test_yuv444p16le_from_to_r10k: duration - enc " << tv_diff(t1, t0) << ", dec " <(r12l_buf.data()), converted, width, height, vc_get_linesize(width, R12L), nullptr); + av_to_uv_convert(to_conv, reinterpret_cast(r12l_buf.data()), converted, width, height, vc_get_linesize(width, R12L), nullptr); TIMER(t2); + av_to_uv_conversion_destroy(&to_conv); to_lavc_vid_conv_destroy(&from_conv); if (getenv("PERF") != nullptr) { @@ -189,13 +191,14 @@ static void yuv444p16le_rg48_encode_decode(int width, int height, char *in, char struct to_lavc_vid_conv *from_conv = to_lavc_vid_conv_init(RG48, width, height, avfmt, 1); auto to_conv = get_av_to_uv_conversion(avfmt, RG48); - assert(to_conv.valid && from_conv != nullptr); + assert(to_conv && from_conv != nullptr); TIMER(t0); struct AVFrame *converted = to_lavc_vid_conv(from_conv, in); TIMER(t1); - av_to_uv_convert(&to_conv, reinterpret_cast(out), converted, width, height, vc_get_linesize(width, RG48), nullptr); + av_to_uv_convert(to_conv, reinterpret_cast(out), converted, width, height, vc_get_linesize(width, RG48), nullptr); TIMER(t2); + av_to_uv_conversion_destroy(&to_conv); to_lavc_vid_conv_destroy(&from_conv); if (getenv("PERF") != nullptr) { @@ -366,10 +369,11 @@ int ff_codec_conversions_test_pX10_from_to_v210() struct to_lavc_vid_conv *from_conv = to_lavc_vid_conv_init(codec, width, height, c, 1); auto to_conv = get_av_to_uv_conversion(c, codec); assert(from_conv != nullptr); - assert(to_conv.valid); + assert(to_conv != nullptr); struct AVFrame *converted = to_lavc_vid_conv(from_conv, (char *) in.data()); - av_to_uv_convert(&to_conv, reinterpret_cast(out.data()), converted, width, height, vc_get_linesize(width, codec), nullptr); + av_to_uv_convert(to_conv, reinterpret_cast(out.data()), converted, width, height, vc_get_linesize(width, codec), nullptr); + av_to_uv_conversion_destroy(&to_conv); to_lavc_vid_conv_destroy(&from_conv); if (getenv("DEBUG_DUMP") != nullptr) {