From 1e22ad2adab194ff65fe20fdda1d451ef30cbaab Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 20 Oct 2021 00:21:44 -0300 Subject: [PATCH 001/894] avcodec/libx264: move sei_data_size out of the for loop Otherwise its value will be reset on each iteration. Signed-off-by: James Almer --- libavcodec/libx264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 13cdd6a022..21f434d06d 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -319,6 +319,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, if (frame) { x264_sei_t *sei = &x4->pic.extra_sei; + unsigned int sei_data_size = 0; for (i = 0; i < x4->pic.img.i_plane; i++) { x4->pic.img.plane[i] = frame->data[i]; @@ -445,7 +446,6 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, for (int j = 0; j < frame->nb_side_data; j++) { AVFrameSideData *side_data = frame->side_data[j]; - unsigned int sei_data_size = 0; void *tmp; x264_sei_payload_t *sei_payload; if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) From 960efa94ff817d3c0761ce7414ddd632cfe7ed74 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 20 Oct 2021 14:40:30 +0200 Subject: [PATCH 002/894] avfilter/vf_v360: make reset_rot option not lose its value Unless -1 value is provided then rotation is reset single time. --- libavfilter/vf_v360.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index ed25e1f07d..c252a2057a 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -164,7 +164,7 @@ static const AVOption v360_options[] = { { "iv_fov", "input vertical field of view", OFFSET(iv_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "iv_fov"}, { "id_fov", "input diagonal field of view", OFFSET(id_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "id_fov"}, {"alpha_mask", "build mask in alpha plane", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "alpha"}, - { "reset_rot", "reset rotation", OFFSET(reset_rot), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "reset_rot"}, + { "reset_rot", "reset rotation", OFFSET(reset_rot), AV_OPT_TYPE_BOOL, {.i64=0}, -1, 1,TFLAGS, "reset_rot"}, { NULL } }; @@ -4962,7 +4962,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar int ret; s->yaw = s->pitch = s->roll = 0.f; - s->reset_rot = 0; + if (s->reset_rot < 0) + s->reset_rot = 0; ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); if (ret < 0) From 5779bd5b2a9281b443a41aebad1be0b1def965ef Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 24 Aug 2021 18:39:13 +0800 Subject: [PATCH 003/894] avformat/mpegts: add support for stream_type 0xd4, which is AVS3 GB/T 17975.1 Information technology-Generic coding of moving pictures and associated audio information-Part 1:Systems Signed-off-by: Limin Wang --- libavformat/mpegts.c | 1 + libavformat/mpegts.h | 1 + libavformat/mpegtsenc.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 44d9298b12..d8cbaa8ced 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -807,6 +807,7 @@ static const StreamType ISO_types[] = { { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, { 0xd2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 }, + { 0xd4, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS3 }, { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h index 910d65af8c..a48f14e768 100644 --- a/libavformat/mpegts.h +++ b/libavformat/mpegts.h @@ -130,6 +130,7 @@ #define STREAM_TYPE_VIDEO_HEVC 0x24 #define STREAM_TYPE_VIDEO_CAVS 0x42 #define STREAM_TYPE_VIDEO_AVS2 0xd2 +#define STREAM_TYPE_VIDEO_AVS3 0xd4 #define STREAM_TYPE_VIDEO_VC1 0xea #define STREAM_TYPE_VIDEO_DIRAC 0xd1 diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index f3b7914175..26fb1f1841 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -369,6 +369,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) case AV_CODEC_ID_AVS2: stream_type = STREAM_TYPE_VIDEO_AVS2; break; + case AV_CODEC_ID_AVS3: + stream_type = STREAM_TYPE_VIDEO_AVS3; + break; case AV_CODEC_ID_DIRAC: stream_type = STREAM_TYPE_VIDEO_DIRAC; break; From 44fe572371f9f00786069b3d4698611e9a34d7ee Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 24 Aug 2021 20:22:25 +0800 Subject: [PATCH 004/894] avformat/mpegtsenc: add AVSV format_identifier for AVS standard Listing of Registered Identifiers: https://smpte-ra.org/registered-mpeg-ts-ids Signed-off-by: Limin Wang --- libavformat/mpegtsenc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 26fb1f1841..184bb52f75 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -789,6 +789,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) put_registration_descriptor(&q, MKTAG('V', 'C', '-', '1')); } else if (stream_type == STREAM_TYPE_VIDEO_HEVC && s->strict_std_compliance <= FF_COMPLIANCE_NORMAL) { put_registration_descriptor(&q, MKTAG('H', 'E', 'V', 'C')); + } else if (stream_type == STREAM_TYPE_VIDEO_CAVS || stream_type == STREAM_TYPE_VIDEO_AVS2 || + stream_type == STREAM_TYPE_VIDEO_AVS3) { + put_registration_descriptor(&q, MKTAG('A', 'V', 'S', 'V')); } break; case AVMEDIA_TYPE_DATA: From 32531333824a76524987c481daba43ffffa43ef0 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 13 Oct 2021 20:23:06 +0800 Subject: [PATCH 005/894] avfilter/af_replaygain: use fabsf() instead of fabs() Signed-off-by: Limin Wang --- libavfilter/af_replaygain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c index 4bf2763bcf..ee0312da82 100644 --- a/libavfilter/af_replaygain.c +++ b/libavfilter/af_replaygain.c @@ -428,7 +428,7 @@ static void butter_filter_stereo_samples(ReplayGainContext *s, // (slowing us down). for (j = -4; j < 0; ++j) - if (fabs(hist_a[i + j]) > 1e-10 || fabs(hist_b[i + j]) > 1e-10) + if (fabsf(hist_a[i + j]) > 1e-10f || fabsf(hist_b[i + j]) > 1e-10f) break; if (!j) { @@ -477,7 +477,7 @@ static void yule_filter_stereo_samples(ReplayGainContext *s, const float *src, // (slowing us down). for (j = -20; j < 0; ++j) - if (fabs(hist_a[i + j]) > 1e-10 || fabs(hist_b[i + j]) > 1e-10) + if (fabsf(hist_a[i + j]) > 1e-10f || fabsf(hist_b[i + j]) > 1e-10f) break; if (!j) { From b22b8e5489bcd4c19ca6beecf1ec055f39cb5c59 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 13 Oct 2021 19:20:29 +0800 Subject: [PATCH 006/894] avfilter/vf_showinfo: small adjustments for the HDR10+ dump summary for the adjustments: 1, remove the extra "," in the ,} ...{0.2004,0.3001,0.4008,0.5005,0.6002,0.7009,0.8006,0.9013,} to ...{0.2004,0.3001,0.4008,0.5005,0.6002,0.7009,0.8006,0.9013} 2, add "," between the } and new field } fraction_bright_pixels to }, fraction_bright_pixels 3, remove the extra space between "} }" ...{0.2004,0.3001,0.4008,0.5005,0.6002,0.7009,0.8006,0.9013,} } to ...{0.2004,0.3001,0.4008,0.5005,0.6002,0.7009,0.8006,0.9013,}} Signed-off-by: Limin Wang --- libavfilter/vf_showinfo.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index c8c7b986b5..ff438e70c6 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -221,7 +221,7 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) av_log(ctx, AV_LOG_INFO, "num_windows: %d, ", hdr_plus->num_windows); for (int w = 1; w < hdr_plus->num_windows; w++) { AVHDRPlusColorTransformParams *params = &hdr_plus->params[w]; - av_log(ctx, AV_LOG_INFO, "window %d { ", w); + av_log(ctx, AV_LOG_INFO, w > 1 ? ", window %d { " : "window %d { ", w); av_log(ctx, AV_LOG_INFO, "window_upper_left_corner: (%5.4f,%5.4f),", av_q2d(params->window_upper_left_corner_x), av_q2d(params->window_upper_left_corner_y)); @@ -242,7 +242,7 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) params->semimajor_axis_external_ellipse); av_log(ctx, AV_LOG_INFO, "semiminor_axis_external_ellipse: %d, ", params->semiminor_axis_external_ellipse); - av_log(ctx, AV_LOG_INFO, "overlap_process_option: %d}, ", + av_log(ctx, AV_LOG_INFO, "overlap_process_option: %d}", params->overlap_process_option); } av_log(ctx, AV_LOG_INFO, "targeted_system_display_maximum_luminance: %9.4f, ", @@ -252,7 +252,7 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) for (int i = 0; i < hdr_plus->num_rows_targeted_system_display_actual_peak_luminance; i++) { av_log(ctx, AV_LOG_INFO, "("); for (int j = 0; j < hdr_plus->num_cols_targeted_system_display_actual_peak_luminance; j++) { - av_log(ctx, AV_LOG_INFO, "%5.4f,", + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", av_q2d(hdr_plus->targeted_system_display_actual_peak_luminance[i][j])); } av_log(ctx, AV_LOG_INFO, ")"); @@ -264,9 +264,9 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) AVHDRPlusColorTransformParams *params = &hdr_plus->params[w]; av_log(ctx, AV_LOG_INFO, "window %d {maxscl: {", w); for (int i = 0; i < 3; i++) { - av_log(ctx, AV_LOG_INFO, "%5.4f,",av_q2d(params->maxscl[i])); + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f",av_q2d(params->maxscl[i])); } - av_log(ctx, AV_LOG_INFO, "} average_maxrgb: %5.4f, ", + av_log(ctx, AV_LOG_INFO, "}, average_maxrgb: %5.4f, ", av_q2d(params->average_maxrgb)); av_log(ctx, AV_LOG_INFO, "distribution_maxrgb: {"); for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { @@ -274,35 +274,35 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) params->distribution_maxrgb[i].percentage, av_q2d(params->distribution_maxrgb[i].percentile)); } - av_log(ctx, AV_LOG_INFO, "} fraction_bright_pixels: %5.4f, ", + av_log(ctx, AV_LOG_INFO, "}, fraction_bright_pixels: %5.4f", av_q2d(params->fraction_bright_pixels)); if (params->tone_mapping_flag) { - av_log(ctx, AV_LOG_INFO, "knee_point: (%5.4f,%5.4f), ", av_q2d(params->knee_point_x), av_q2d(params->knee_point_y)); + av_log(ctx, AV_LOG_INFO, ", knee_point: (%5.4f,%5.4f), ", av_q2d(params->knee_point_x), av_q2d(params->knee_point_y)); av_log(ctx, AV_LOG_INFO, "bezier_curve_anchors: {"); for (int i = 0; i < params->num_bezier_curve_anchors; i++) { - av_log(ctx, AV_LOG_INFO, "%5.4f,", + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", av_q2d(params->bezier_curve_anchors[i])); } - av_log(ctx, AV_LOG_INFO, "} "); + av_log(ctx, AV_LOG_INFO, "}"); } if (params->color_saturation_mapping_flag) { - av_log(ctx, AV_LOG_INFO, "color_saturation_weight: %5.4f", + av_log(ctx, AV_LOG_INFO, ", color_saturation_weight: %5.4f", av_q2d(params->color_saturation_weight)); } - av_log(ctx, AV_LOG_INFO, "} "); + av_log(ctx, AV_LOG_INFO, "}"); } if (hdr_plus->mastering_display_actual_peak_luminance_flag) { - av_log(ctx, AV_LOG_INFO, "mastering_display_actual_peak_luminance: {"); + av_log(ctx, AV_LOG_INFO, ", mastering_display_actual_peak_luminance: {"); for (int i = 0; i < hdr_plus->num_rows_mastering_display_actual_peak_luminance; i++) { av_log(ctx, AV_LOG_INFO, "("); for (int j = 0; j < hdr_plus->num_cols_mastering_display_actual_peak_luminance; j++) { - av_log(ctx, AV_LOG_INFO, " %5.4f,", + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", av_q2d(hdr_plus->mastering_display_actual_peak_luminance[i][j])); } av_log(ctx, AV_LOG_INFO, ")"); } - av_log(ctx, AV_LOG_INFO, "} "); + av_log(ctx, AV_LOG_INFO, "}"); } } From 0feb7c86019794ac31dec2869dae839f0ad4f0ef Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 13 Oct 2021 19:06:40 +0800 Subject: [PATCH 007/894] avcodec/hevc_sei: remove the duplicate check Signed-off-by: Limin Wang --- libavcodec/hevc_sei.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 29d0346287..7fd822652e 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -181,9 +181,6 @@ static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetB { int ret; - if (size < 3) - return AVERROR_INVALIDDATA; - ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer + get_bits_count(gb) / 8, size); if (ret < 0) From cd38fbf4f7992dec59da6f76344e6e6c1826efea Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 13 Oct 2021 19:37:10 +0800 Subject: [PATCH 008/894] avcodec/atsc_a53: use AVERROR_INVALIDDATA Signed-off-by: Limin Wang --- libavcodec/atsc_a53.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/atsc_a53.c b/libavcodec/atsc_a53.c index 2d89ef50b9..29ec71bc5f 100644 --- a/libavcodec/atsc_a53.c +++ b/libavcodec/atsc_a53.c @@ -73,7 +73,7 @@ int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size) int ret, cc_count; if (size < 3) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; ret = init_get_bits8(&gb, data, size); if (ret < 0) @@ -95,12 +95,12 @@ int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size) /* 3 bytes per CC plus one byte marker_bits at the end */ if (cc_count * 3 >= (get_bits_left(&gb) >> 3)) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; new_size = (old_size + cc_count * 3); if (new_size > INT_MAX) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; /* Allow merging of the cc data from two fields. */ ret = av_buffer_realloc(pbuf, new_size); From 2aa343bb6f8577faff99ecb29f2a71011ceb35b1 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 21 Oct 2021 16:13:54 +0530 Subject: [PATCH 009/894] doc/filters: add notes for varblur --- doc/filters.texi | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 22e604f712..93eadda45d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -21706,20 +21706,25 @@ Default is universal. @section varblur Apply variable blur filter by using 2nd video stream to set blur radius. +The 2nd stream must have the same dimensions. This filter accepts the following options: @table @option @item min_r -Set min allowed radius. By default is 0. Allowed range is from 0 to 254. +Set min allowed radius. Allowed range is from 0 to 254. Default is 0. @item max_r -Set max allowed radius. By default is 8. Allowed range is from 1 to 255. +Set max allowed radius. Allowed range is from 1 to 255. Default is 8. @item planes -Set which planes to process. By default all are used. +Set which planes to process. By default, all are used. @end table The @code{varblur} filter also supports the @ref{framesync} options. +@subsection Commands + +This filter supports all the above options as @ref{commands}. + @section vectorscope Display 2 color component values in the two dimensional graph (which is called From c13a2f701db21d3ea2763ca85cb5fd21e032fd13 Mon Sep 17 00:00:00 2001 From: "the.real.laplace@gmail.com" Date: Mon, 18 Oct 2021 14:29:48 +0300 Subject: [PATCH 010/894] avfilter/vf_eq: add support for alpha channel Signed-off-by: Michael Niedermayer --- libavfilter/vf_eq.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c index 4a0d85e8e5..80ab21efb3 100644 --- a/libavfilter/vf_eq.c +++ b/libavfilter/vf_eq.c @@ -236,9 +236,9 @@ static const enum AVPixelFormat pixel_fmts_eq[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; @@ -281,12 +281,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); } - if (eq->param[i].adjust) - eq->param[i].adjust(&eq->param[i], out->data[i], out->linesize[i], - in->data[i], in->linesize[i], w, h); - else + if (i == 3 || !eq->param[i].adjust) av_image_copy_plane(out->data[i], out->linesize[i], in->data[i], in->linesize[i], w, h); + + else + eq->param[i].adjust(&eq->param[i], out->data[i], out->linesize[i], + in->data[i], in->linesize[i], w, h); } av_frame_free(&in); From e154353fdb73dc1b3c1519350244d5346f761850 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 20 Oct 2021 19:51:08 +0200 Subject: [PATCH 011/894] avutil/mathematics: Document av_rescale_rnd() behavior on non int64 results Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer --- libavutil/mathematics.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index 54901800ba..64d4137a60 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -134,6 +134,7 @@ int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; * * The operation is mathematically equivalent to `a * b / c`, but writing that * directly can overflow, and does not support different rounding methods. + * If the result is not representable then INT64_MIN is returned. * * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() */ From 6bba9d960b51da6d4528a81bbcd3da1d606cb124 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 12 Oct 2021 14:59:49 +0200 Subject: [PATCH 012/894] tools/target_dec_fuzzer: Adjust threshold for MXPEG Fixes: Timeout Fixes: 39813/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MXPEG_fuzzer-6010298067189760 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 8800231691..1a790f6642 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -184,6 +184,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_MSRLE: maxpixels /= 16; break; case AV_CODEC_ID_MSS2: maxpixels /= 16384; break; case AV_CODEC_ID_MSZH: maxpixels /= 128; break; + case AV_CODEC_ID_MXPEG: maxpixels /= 128; break; case AV_CODEC_ID_OPUS: maxsamples /= 16384; break; case AV_CODEC_ID_PNG: maxpixels /= 128; break; case AV_CODEC_ID_APNG: maxpixels /= 128; break; From f24028c798397af720acb838357785aa705a8122 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 15 Oct 2021 00:04:59 +0200 Subject: [PATCH 013/894] avcodec/ttadsp: Fix integer overflows in tta_filter_process_c() Fixes: signed integer overflow: 822841647 + 1647055738 cannot be represented in type 'int' Fixes: 39935/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TTA_fuzzer-4592657142251520 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/ttadsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/ttadsp.c b/libavcodec/ttadsp.c index 1d1443aee0..99dd66a0c2 100644 --- a/libavcodec/ttadsp.c +++ b/libavcodec/ttadsp.c @@ -47,9 +47,9 @@ static void tta_filter_process_c(int32_t *qmi, int32_t *dx, int32_t *dl, *error = *in; *in += (round >> shift); - dl[4] = -dl[5]; dl[5] = -dl[6]; - dl[6] = *in - dl[7]; dl[7] = *in; - dl[5] += dl[6]; dl[4] += dl[5]; + dl[4] = -(unsigned)dl[5]; dl[5] = -(unsigned)dl[6]; + dl[6] = *in -(unsigned)dl[7]; dl[7] = *in; + dl[5] += (unsigned)dl[6]; dl[4] += (unsigned)dl[5]; } av_cold void ff_ttadsp_init(TTADSPContext *c) From a987b5c9ee282de4a4ed2aaf8f2640ed09f705e9 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Wed, 20 Oct 2021 14:52:06 +0100 Subject: [PATCH 014/894] avformat/mov: Use av_rescale when calculating bit rate It is less susceptible to overflows. Signed-off-by: Derek Buitenhuis --- libavformat/mov.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 57c67e3aac..841818b547 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -7989,12 +7989,14 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; if (st->duration > 0) { - if (sc->data_size > INT64_MAX / sc->time_scale / 8) { + /* Akin to sc->data_size * 8 * sc->time_scale / st->duration but accounting for overflows. */ + st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, st->duration); + if (st->codecpar->bit_rate == INT64_MIN) { av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", sc->data_size, sc->time_scale); + st->codecpar->bit_rate = 0; return AVERROR_INVALIDDATA; } - st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration; } } } @@ -8004,13 +8006,14 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; if (sc->duration_for_fps > 0) { - if (sc->data_size > INT64_MAX / sc->time_scale / 8) { + /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */ + st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps); + if (st->codecpar->bit_rate == INT64_MIN) { av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", sc->data_size, sc->time_scale); + st->codecpar->bit_rate = 0; return AVERROR_INVALIDDATA; } - st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / - sc->duration_for_fps; } } } From 7216458c96a7635af5ae7428fdcad6c81ba870d7 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Tue, 12 Oct 2021 14:48:31 +0100 Subject: [PATCH 015/894] avformat/mov: Do not hard fail if bit rate calculation overflows unless in explode mode bit_rate is not a critical field, and we shouln't hard fail if we can't caluclate it due to a large timebase - it needlessly breaks valid files. Signed-off-by: Derek Buitenhuis --- libavformat/mov.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 841818b547..263d605c41 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -7992,10 +7992,11 @@ static int mov_read_header(AVFormatContext *s) /* Akin to sc->data_size * 8 * sc->time_scale / st->duration but accounting for overflows. */ st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, st->duration); if (st->codecpar->bit_rate == INT64_MIN) { - av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", + av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", sc->data_size, sc->time_scale); st->codecpar->bit_rate = 0; - return AVERROR_INVALIDDATA; + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; } } } @@ -8009,10 +8010,11 @@ static int mov_read_header(AVFormatContext *s) /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */ st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps); if (st->codecpar->bit_rate == INT64_MIN) { - av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", + av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", sc->data_size, sc->time_scale); st->codecpar->bit_rate = 0; - return AVERROR_INVALIDDATA; + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; } } } From f0ad40b525b5f882f048cf69139bbe496ba59eea Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 21 Oct 2021 21:05:02 +0200 Subject: [PATCH 016/894] avfilter/vf_bilateral: remove unneeded multiplications --- libavfilter/vf_bilateral.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c index 2a4a3df6cc..61c9084933 100644 --- a/libavfilter/vf_bilateral.c +++ b/libavfilter/vf_bilateral.c @@ -186,11 +186,11 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * *temp_factor_x++ = fc = inv_alpha_ + alpha_ * fp; \ fp = fc; \ } \ - --temp_x; *temp_x = 0.5f*((*temp_x) + (*--in_x)); \ + --temp_x; *temp_x = ((*temp_x) + (*--in_x)); \ tpr = *--texture_x; \ ypr = *in_x; \ \ - --temp_factor_x; *temp_factor_x = 0.5f*((*temp_factor_x) + 1); \ + --temp_factor_x; *temp_factor_x = ((*temp_factor_x) + 1); \ fp = 1; \ \ for (int x = width - 2; x >= 0; x--) { \ @@ -200,13 +200,13 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * float alpha_ = range_table[range_dist]; \ \ ycr = inv_alpha_ * (*--in_x) + alpha_ * ypr; \ - --temp_x; *temp_x = 0.5f*((*temp_x) + ycr); \ + --temp_x; *temp_x = ((*temp_x) + ycr); \ tpr = tcr; \ ypr = ycr; \ \ fc = inv_alpha_ + alpha_*fp; \ --temp_factor_x; \ - *temp_factor_x = 0.5f*((*temp_factor_x) + fc); \ + *temp_factor_x = ((*temp_factor_x) + fc); \ fp = fc; \ } \ } \ @@ -238,14 +238,14 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * ypf = line_factor_b; \ memcpy(ypf, &in_factor[h1 * width], sizeof(float) * width); \ for (int x = 0; x < width; x++) \ - map_factor_b[h1 * width + x] = 0.5f*(map_factor_b[h1 * width + x] + ypf[x]); \ + map_factor_b[h1 * width + x] = (map_factor_b[h1 * width + x] + ypf[x]); \ \ ycy = slice_factor_a; \ ypy = slice_factor_b; \ memcpy(ypy, &img_temp[h1 * width], sizeof(float) * width); \ for (int x = 0, k = 0; x < width; x++) { \ int idx = h1 * width + x; \ - img_out_f[idx] = 0.5f*(img_out_f[idx] + ypy[k++]) / map_factor_b[h1 * width + x]; \ + img_out_f[idx] = (img_out_f[idx] + ypy[k++]) / map_factor_b[h1 * width + x]; \ } \ \ for (int y = h1 - 1; y >= 0; y--) { \ @@ -270,11 +270,11 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * float ycc, fcc = inv_alpha_*(*xcf++) + alpha_*(*ypf_++); \ \ *ycf_++ = fcc; \ - *factor_ = 0.5f * (*factor_ + fcc); \ + *factor_ = (*factor_ + fcc); \ \ ycc = inv_alpha_*(*xcy++) + alpha_*(*ypy_++); \ *ycy_++ = ycc; \ - *out_ = 0.5f * (*out_ + ycc) / (*factor_); \ + *out_ = (*out_ + ycc) / (*factor_); \ out_++; \ factor_++; \ } \ From 4e4057e437972988e23b9d36092f17818871ac93 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 21 Oct 2021 21:15:48 +0200 Subject: [PATCH 017/894] avfilter/vf_bilateral: remove unused arguments --- libavfilter/vf_bilateral.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c index 61c9084933..aecde64860 100644 --- a/libavfilter/vf_bilateral.c +++ b/libavfilter/vf_bilateral.c @@ -143,7 +143,6 @@ static int config_input(AVFilterLink *inlink) #define BILATERAL(type, name) \ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t *ddst, \ - float sigma_spatial, float sigma_range, \ int width, int height, int src_linesize, int dst_linesize) \ { \ type *dst = (type *)ddst; \ @@ -314,11 +313,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } if (s->depth <= 8) - bilateral_byte(s, in->data[plane], out->data[plane], s->sigmaS, s->sigmaR, + bilateral_byte(s, in->data[plane], out->data[plane], s->planewidth[plane], s->planeheight[plane], in->linesize[plane], out->linesize[plane]); else - bilateral_word(s, in->data[plane], out->data[plane], s->sigmaS, s->sigmaR, + bilateral_word(s, in->data[plane], out->data[plane], s->planewidth[plane], s->planeheight[plane], in->linesize[plane] / 2, out->linesize[plane] / 2); } From cf0881bcfc88b4afb62a4647b0e09809e9612a5b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 21 Oct 2021 21:59:14 +0200 Subject: [PATCH 018/894] avfilter/vf_bilateral: properly round float result --- libavfilter/vf_bilateral.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c index aecde64860..8fe341f70d 100644 --- a/libavfilter/vf_bilateral.c +++ b/libavfilter/vf_bilateral.c @@ -284,7 +284,7 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * \ for (int i = 0; i < height; i++) \ for (int j = 0; j < width; j++) \ - dst[j + i * dst_linesize] = img_out_f[i * width + j]; \ + dst[j + i * dst_linesize] = lrintf(img_out_f[i * width + j]); \ } BILATERAL(uint8_t, byte) From 444cf3fca8dab2da9b95cc36920667f76d0f796c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 22 Oct 2021 09:34:51 +0200 Subject: [PATCH 019/894] avfilter/vf_bilateral: add direct aka writable frame support --- libavfilter/vf_bilateral.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c index 8fe341f70d..b236efe6c3 100644 --- a/libavfilter/vf_bilateral.c +++ b/libavfilter/vf_bilateral.c @@ -297,18 +297,23 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); } - av_frame_copy_props(out, in); for (int plane = 0; plane < s->nb_planes; plane++) { if (!(s->planes & (1 << plane))) { - av_image_copy_plane(out->data[plane], out->linesize[plane], - in->data[plane], in->linesize[plane], - s->planewidth[plane] * ((s->depth + 7) / 8), s->planeheight[plane]); + if (out != in) + av_image_copy_plane(out->data[plane], out->linesize[plane], + in->data[plane], in->linesize[plane], + s->planewidth[plane] * ((s->depth + 7) / 8), s->planeheight[plane]); continue; } @@ -322,7 +327,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) in->linesize[plane] / 2, out->linesize[plane] / 2); } - av_frame_free(&in); + if (out != in) + av_frame_free(&in); return ff_filter_frame(outlink, out); } From 7d463be590680bcce42aa4039616ac9dfac117b0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 22 Oct 2021 11:01:23 +0200 Subject: [PATCH 020/894] avfilter/vf_bilateral: add slice threading support --- libavfilter/vf_bilateral.c | 457 ++++++++++++++++++++++++------------- 1 file changed, 293 insertions(+), 164 deletions(-) diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c index b236efe6c3..41dc38d6f2 100644 --- a/libavfilter/vf_bilateral.c +++ b/libavfilter/vf_bilateral.c @@ -36,6 +36,7 @@ typedef struct BilateralContext { float sigmaR; int planes; + int nb_threads; int nb_planes; int depth; int planewidth[4]; @@ -44,14 +45,14 @@ typedef struct BilateralContext { float alpha; float range_table[65536]; - float *img_out_f; - float *img_temp; - float *map_factor_a; - float *map_factor_b; - float *slice_factor_a; - float *slice_factor_b; - float *line_factor_a; - float *line_factor_b; + float *img_out_f[4]; + float *img_temp[4]; + float *map_factor_a[4]; + float *map_factor_b[4]; + float *slice_factor_a[4]; + float *slice_factor_b[4]; + float *line_factor_a[4]; + float *line_factor_b[4]; } BilateralContext; #define OFFSET(x) offsetof(BilateralContext, x) @@ -102,6 +103,10 @@ static int config_params(AVFilterContext *ctx) return 0; } +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -109,7 +114,6 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); s->depth = desc->comp[0].depth; - config_params(ctx); s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); @@ -118,133 +122,169 @@ static int config_input(AVFilterLink *inlink) s->planeheight[0] = s->planeheight[3] = inlink->h; s->nb_planes = av_pix_fmt_count_planes(inlink->format); + s->nb_threads = ff_filter_get_nb_threads(ctx); - s->img_out_f = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->img_temp = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->map_factor_a = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->map_factor_b = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->slice_factor_a = av_calloc(inlink->w, sizeof(float)); - s->slice_factor_b = av_calloc(inlink->w, sizeof(float)); - s->line_factor_a = av_calloc(inlink->w, sizeof(float)); - s->line_factor_b = av_calloc(inlink->w, sizeof(float)); + for (int p = 0; p < s->nb_planes; p++) { + const int w = s->planewidth[p]; + const int h = s->planeheight[p]; - if (!s->img_out_f || - !s->img_temp || - !s->map_factor_a || - !s->map_factor_b || - !s->slice_factor_a || - !s->slice_factor_a || - !s->line_factor_a || - !s->line_factor_a) - return AVERROR(ENOMEM); + s->img_out_f[p] = av_calloc(w * h, sizeof(float)); + s->img_temp[p] = av_calloc(w * h, sizeof(float)); + s->map_factor_a[p] = av_calloc(w * h, sizeof(float)); + s->map_factor_b[p] = av_calloc(w * h, sizeof(float)); + s->slice_factor_a[p] = av_calloc(w, sizeof(float)); + s->slice_factor_b[p] = av_calloc(w, sizeof(float)); + s->line_factor_a[p] = av_calloc(w, sizeof(float)); + s->line_factor_b[p] = av_calloc(w, sizeof(float)); + + if (!s->img_out_f[p] || + !s->img_temp[p] || + !s->map_factor_a[p] || + !s->map_factor_b[p] || + !s->slice_factor_a[p] || + !s->slice_factor_a[p] || + !s->line_factor_a[p] || + !s->line_factor_a[p]) + return AVERROR(ENOMEM); + } return 0; } -#define BILATERAL(type, name) \ -static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t *ddst, \ - int width, int height, int src_linesize, int dst_linesize) \ -{ \ - type *dst = (type *)ddst; \ - const type *src = (const type *)ssrc; \ - float *img_out_f = s->img_out_f, *img_temp = s->img_temp; \ - float *map_factor_a = s->map_factor_a, *map_factor_b = s->map_factor_b; \ - float *slice_factor_a = s->slice_factor_a, *slice_factor_b = s->slice_factor_b; \ - float *line_factor_a = s->line_factor_a, *line_factor_b = s->line_factor_b; \ - const float *range_table = s->range_table; \ - const float alpha = s->alpha; \ - float ypr, ycr, *ycy, *ypy, *xcy, fp, fc; \ - const float inv_alpha_ = 1.f - alpha; \ - float *ycf, *ypf, *xcf, *in_factor; \ - const type *tcy, *tpy; \ - int h1; \ - \ - for (int y = 0; y < height; y++) { \ - float *temp_factor_x, *temp_x = &img_temp[y * width]; \ - const type *in_x = &src[y * src_linesize]; \ - const type *texture_x = &src[y * src_linesize]; \ - type tpr; \ - \ - *temp_x++ = ypr = *in_x++; \ - tpr = *texture_x++; \ - \ - temp_factor_x = &map_factor_a[y * width]; \ - *temp_factor_x++ = fp = 1; \ - \ - for (int x = 1; x < width; x++) { \ - float alpha_; \ - int range_dist; \ - type tcr = *texture_x++; \ - type dr = abs(tcr - tpr); \ - \ - range_dist = dr; \ - alpha_ = range_table[range_dist]; \ - *temp_x++ = ycr = inv_alpha_*(*in_x++) + alpha_*ypr; \ - tpr = tcr; \ - ypr = ycr; \ - *temp_factor_x++ = fc = inv_alpha_ + alpha_ * fp; \ - fp = fc; \ - } \ - --temp_x; *temp_x = ((*temp_x) + (*--in_x)); \ - tpr = *--texture_x; \ - ypr = *in_x; \ - \ - --temp_factor_x; *temp_factor_x = ((*temp_factor_x) + 1); \ - fp = 1; \ - \ - for (int x = width - 2; x >= 0; x--) { \ - type tcr = *--texture_x; \ - type dr = abs(tcr - tpr); \ - int range_dist = dr; \ - float alpha_ = range_table[range_dist]; \ - \ - ycr = inv_alpha_ * (*--in_x) + alpha_ * ypr; \ - --temp_x; *temp_x = ((*temp_x) + ycr); \ - tpr = tcr; \ - ypr = ycr; \ - \ - fc = inv_alpha_ + alpha_*fp; \ - --temp_factor_x; \ - *temp_factor_x = ((*temp_factor_x) + fc); \ - fp = fc; \ - } \ - } \ - memcpy(img_out_f, img_temp, sizeof(float) * width); \ - \ - in_factor = map_factor_a; \ - memcpy(map_factor_b, in_factor, sizeof(float) * width); \ - for (int y = 1; y < height; y++) { \ - tpy = &src[(y - 1) * src_linesize]; \ - tcy = &src[y * src_linesize]; \ - xcy = &img_temp[y * width]; \ - ypy = &img_out_f[(y - 1) * width]; \ - ycy = &img_out_f[y * width]; \ - \ - xcf = &in_factor[y * width]; \ - ypf = &map_factor_b[(y - 1) * width]; \ - ycf = &map_factor_b[y * width]; \ - for (int x = 0; x < width; x++) { \ - type dr = abs((*tcy++) - (*tpy++)); \ - int range_dist = dr; \ - float alpha_ = range_table[range_dist]; \ - \ - *ycy++ = inv_alpha_*(*xcy++) + alpha_*(*ypy++); \ - *ycf++ = inv_alpha_*(*xcf++) + alpha_*(*ypf++); \ - } \ - } \ - h1 = height - 1; \ - ycf = line_factor_a; \ - ypf = line_factor_b; \ - memcpy(ypf, &in_factor[h1 * width], sizeof(float) * width); \ - for (int x = 0; x < width; x++) \ - map_factor_b[h1 * width + x] = (map_factor_b[h1 * width + x] + ypf[x]); \ - \ - ycy = slice_factor_a; \ - ypy = slice_factor_b; \ - memcpy(ypy, &img_temp[h1 * width], sizeof(float) * width); \ - for (int x = 0, k = 0; x < width; x++) { \ - int idx = h1 * width + x; \ - img_out_f[idx] = (img_out_f[idx] + ypy[k++]) / map_factor_b[h1 * width + x]; \ +#define BILATERAL_H(type, name) \ +static void bilateralh_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \ + int jobnr, int nb_jobs, int plane) \ +{ \ + const int width = s->planewidth[plane]; \ + const int height = s->planeheight[plane]; \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + const int src_linesize = in->linesize[plane] / sizeof(type); \ + const type *src = (const type *)in->data[plane]; \ + float *img_temp = s->img_temp[plane]; \ + float *map_factor_a = s->map_factor_a[plane]; \ + const float *const range_table = s->range_table; \ + const float alpha = s->alpha; \ + float ypr, ycr, fp, fc; \ + const float inv_alpha_ = 1.f - alpha; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + float *temp_factor_x, *temp_x = &img_temp[y * width]; \ + const type *in_x = &src[y * src_linesize]; \ + const type *texture_x = &src[y * src_linesize]; \ + type tpr; \ + \ + *temp_x++ = ypr = *in_x++; \ + tpr = *texture_x++; \ + \ + temp_factor_x = &map_factor_a[y * width]; \ + *temp_factor_x++ = fp = 1; \ + \ + for (int x = 1; x < width; x++) { \ + float alpha_; \ + int range_dist; \ + type tcr = *texture_x++; \ + type dr = abs(tcr - tpr); \ + \ + range_dist = dr; \ + alpha_ = range_table[range_dist]; \ + *temp_x++ = ycr = inv_alpha_*(*in_x++) + alpha_*ypr; \ + tpr = tcr; \ + ypr = ycr; \ + *temp_factor_x++ = fc = inv_alpha_ + alpha_ * fp; \ + fp = fc; \ + } \ + --temp_x; *temp_x = ((*temp_x) + (*--in_x)); \ + tpr = *--texture_x; \ + ypr = *in_x; \ + \ + --temp_factor_x; *temp_factor_x = ((*temp_factor_x) + 1); \ + fp = 1; \ + \ + for (int x = width - 2; x >= 0; x--) { \ + type tcr = *--texture_x; \ + type dr = abs(tcr - tpr); \ + int range_dist = dr; \ + float alpha_ = range_table[range_dist]; \ + \ + ycr = inv_alpha_ * (*--in_x) + alpha_ * ypr; \ + --temp_x; *temp_x = ((*temp_x) + ycr); \ + tpr = tcr; \ + ypr = ycr; \ + \ + fc = inv_alpha_ + alpha_*fp; \ + --temp_factor_x; \ + *temp_factor_x = ((*temp_factor_x) + fc); \ + fp = fc; \ + } \ + } \ +} + +BILATERAL_H(uint8_t, byte) +BILATERAL_H(uint16_t, word) + +#define BILATERAL_V(type, name) \ +static void bilateralv_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \ + int jobnr, int nb_jobs, int plane) \ +{ \ + const int width = s->planewidth[plane]; \ + const int height = s->planeheight[plane]; \ + const int slice_start = (width * jobnr) / nb_jobs; \ + const int slice_end = (width * (jobnr+1)) / nb_jobs; \ + const int src_linesize = in->linesize[plane] / sizeof(type); \ + const type *src = (const type *)in->data[plane] + slice_start; \ + float *img_out_f = s->img_out_f[plane] + slice_start; \ + float *img_temp = s->img_temp[plane] + slice_start; \ + float *map_factor_a = s->map_factor_a[plane] + slice_start; \ + float *map_factor_b = s->map_factor_b[plane] + slice_start; \ + float *slice_factor_a = s->slice_factor_a[plane] + slice_start; \ + float *slice_factor_b = s->slice_factor_b[plane] + slice_start; \ + float *line_factor_a = s->line_factor_a[plane] + slice_start; \ + float *line_factor_b = s->line_factor_b[plane] + slice_start; \ + const float *const range_table = s->range_table; \ + const float alpha = s->alpha; \ + float *ycy, *ypy, *xcy; \ + const float inv_alpha_ = 1.f - alpha; \ + float *ycf, *ypf, *xcf, *in_factor; \ + const type *tcy, *tpy; \ + int h1; \ + \ + memcpy(img_out_f, img_temp, sizeof(float) * (slice_end - slice_start)); \ + \ + in_factor = map_factor_a; \ + memcpy(map_factor_b, in_factor, sizeof(float) * (slice_end - slice_start)); \ + for (int y = 1; y < height; y++) { \ + tpy = &src[(y - 1) * src_linesize]; \ + tcy = &src[y * src_linesize]; \ + xcy = &img_temp[y * width]; \ + ypy = &img_out_f[(y - 1) * width]; \ + ycy = &img_out_f[y * width]; \ + \ + xcf = &in_factor[y * width]; \ + ypf = &map_factor_b[(y - 1) * width]; \ + ycf = &map_factor_b[y * width]; \ + for (int x = 0; x < slice_end - slice_start; x++) { \ + type dr = abs((*tcy++) - (*tpy++)); \ + int range_dist = dr; \ + float alpha_ = range_table[range_dist]; \ + \ + *ycy++ = inv_alpha_*(*xcy++) + alpha_*(*ypy++); \ + *ycf++ = inv_alpha_*(*xcf++) + alpha_*(*ypf++); \ + } \ + } \ + h1 = height - 1; \ + ycf = line_factor_a; \ + ypf = line_factor_b; \ + memcpy(ypf, &in_factor[h1 * width], sizeof(float) * (slice_end - slice_start)); \ + for (int x = 0, k = 0; x < slice_end - slice_start; x++) \ + map_factor_b[h1 * width + x] = (map_factor_b[h1 * width + x] + ypf[k++]); \ + \ + ycy = slice_factor_a; \ + ypy = slice_factor_b; \ + memcpy(ypy, &img_temp[h1 * width], sizeof(float) * (slice_end - slice_start)); \ + for (int x = 0, k = 0; x < slice_end - slice_start; x++) { \ + int idx = h1 * width + x; \ + img_out_f[idx] = (img_out_f[idx] + ypy[k++]) / map_factor_b[h1 * width + x]; \ } \ \ for (int y = h1 - 1; y >= 0; y--) { \ @@ -262,7 +302,7 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * ycf_ = ycf; \ ypf_ = ypf; \ factor_ = &map_factor_b[y * width]; \ - for (int x = 0; x < width; x++) { \ + for (int x = 0; x < slice_end - slice_start; x++) { \ type dr = abs((*tcy++) - (*tpy++)); \ int range_dist = dr; \ float alpha_ = range_table[range_dist]; \ @@ -281,20 +321,119 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * ypy = ycy; \ ypf = ycf; \ } \ - \ - for (int i = 0; i < height; i++) \ - for (int j = 0; j < width; j++) \ - dst[j + i * dst_linesize] = lrintf(img_out_f[i * width + j]); \ } -BILATERAL(uint8_t, byte) -BILATERAL(uint16_t, word) +BILATERAL_V(uint8_t, byte) +BILATERAL_V(uint16_t, word) + +#define BILATERAL_O(type, name) \ +static void bilateralo_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \ + int jobnr, int nb_jobs, int plane) \ +{ \ + const int width = s->planewidth[plane]; \ + const int height = s->planeheight[plane]; \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + const int dst_linesize = out->linesize[plane] / sizeof(type); \ + \ + for (int i = slice_start; i < slice_end; i++) { \ + type *dst = (type *)out->data[plane] + i * dst_linesize; \ + const float *const img_out_f = s->img_out_f[plane] + i * width; \ + for (int j = 0; j < width; j++) \ + dst[j] = lrintf(img_out_f[j]); \ + } \ +} + +BILATERAL_O(uint8_t, byte) +BILATERAL_O(uint16_t, word) + +static int bilateralh_planes(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + BilateralContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int plane = 0; plane < s->nb_planes; plane++) { + if (!(s->planes & (1 << plane))) + continue; + + if (s->depth <= 8) + bilateralh_byte(s, out, in, jobnr, nb_jobs, plane); + else + bilateralh_word(s, out, in, jobnr, nb_jobs, plane); + } + + return 0; +} + +static int bilateralv_planes(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + BilateralContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int plane = 0; plane < s->nb_planes; plane++) { + if (!(s->planes & (1 << plane))) + continue; + + if (s->depth <= 8) + bilateralv_byte(s, out, in, jobnr, nb_jobs, plane); + else + bilateralv_word(s, out, in, jobnr, nb_jobs, plane); + } + + return 0; +} + +static int bilateralo_planes(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + BilateralContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int plane = 0; plane < s->nb_planes; plane++) { + if (!(s->planes & (1 << plane))) { + if (out != in) { + const int height = s->planeheight[plane]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; + const int width = s->planewidth[plane]; + const int linesize = in->linesize[plane]; + const int dst_linesize = out->linesize[plane]; + const uint8_t *src = in->data[plane]; + uint8_t *dst = out->data[plane]; + + av_image_copy_plane(dst + slice_start * dst_linesize, + dst_linesize, + src + slice_start * linesize, + linesize, + width * ((s->depth + 7) / 8), + slice_end - slice_start); + } + continue; + } + + if (s->depth <= 8) + bilateralo_byte(s, out, in, jobnr, nb_jobs, plane); + else + bilateralo_word(s, out, in, jobnr, nb_jobs, plane); + } + + return 0; +} static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; BilateralContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; if (av_frame_is_writable(in)) { @@ -308,24 +447,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - for (int plane = 0; plane < s->nb_planes; plane++) { - if (!(s->planes & (1 << plane))) { - if (out != in) - av_image_copy_plane(out->data[plane], out->linesize[plane], - in->data[plane], in->linesize[plane], - s->planewidth[plane] * ((s->depth + 7) / 8), s->planeheight[plane]); - continue; - } - - if (s->depth <= 8) - bilateral_byte(s, in->data[plane], out->data[plane], - s->planewidth[plane], s->planeheight[plane], - in->linesize[plane], out->linesize[plane]); - else - bilateral_word(s, in->data[plane], out->data[plane], - s->planewidth[plane], s->planeheight[plane], - in->linesize[plane] / 2, out->linesize[plane] / 2); - } + td.in = in; + td.out = out; + ff_filter_execute(ctx, bilateralh_planes, &td, NULL, s->nb_threads); + ff_filter_execute(ctx, bilateralv_planes, &td, NULL, s->nb_threads); + ff_filter_execute(ctx, bilateralo_planes, &td, NULL, s->nb_threads); if (out != in) av_frame_free(&in); @@ -336,14 +462,16 @@ static av_cold void uninit(AVFilterContext *ctx) { BilateralContext *s = ctx->priv; - av_freep(&s->img_out_f); - av_freep(&s->img_temp); - av_freep(&s->map_factor_a); - av_freep(&s->map_factor_b); - av_freep(&s->slice_factor_a); - av_freep(&s->slice_factor_b); - av_freep(&s->line_factor_a); - av_freep(&s->line_factor_b); + for (int p = 0; p < s->nb_planes; p++) { + av_freep(&s->img_out_f[p]); + av_freep(&s->img_temp[p]); + av_freep(&s->map_factor_a[p]); + av_freep(&s->map_factor_b[p]); + av_freep(&s->slice_factor_a[p]); + av_freep(&s->slice_factor_b[p]); + av_freep(&s->line_factor_a[p]); + av_freep(&s->line_factor_b[p]); + } } static int process_command(AVFilterContext *ctx, @@ -386,6 +514,7 @@ const AVFilter ff_vf_bilateral = { FILTER_INPUTS(bilateral_inputs), FILTER_OUTPUTS(bilateral_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, .process_command = process_command, }; From eda2a50c8e9381a357f936a190659bb039e0c038 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 22 Oct 2021 13:47:16 +0200 Subject: [PATCH 021/894] avfilter/vf_selectivecolor: no need to use doubles --- libavfilter/vf_selectivecolor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_selectivecolor.c b/libavfilter/vf_selectivecolor.c index 9ace3ce4a6..ea4b5dfee2 100644 --- a/libavfilter/vf_selectivecolor.c +++ b/libavfilter/vf_selectivecolor.c @@ -223,7 +223,7 @@ static int parse_psfile(AVFilterContext *ctx, const char *fname) int k; for (k = 0; k < FF_ARRAY_ELEMS(s->cmyk_adjust[0]); k++) { READ16(val); - s->cmyk_adjust[i][k] = val / 100.; + s->cmyk_adjust[i][k] = val / 100.f; } ret = register_range(s, i); if (ret < 0) @@ -299,11 +299,11 @@ static const enum AVPixelFormat pix_fmts[] = { static inline int comp_adjust(int scale, float value, float adjust, float k, int correction_method) { const float min = -value; - const float max = 1. - value; - float res = (-1. - adjust) * k - adjust; + const float max = 1.f - value; + float res = (-1.f - adjust) * k - adjust; if (correction_method == CORRECTION_METHOD_RELATIVE) res *= max; - return lrint(av_clipf(res, min, max) * scale); + return lrintf(av_clipf(res, min, max) * scale); } #define DECLARE_SELECTIVE_COLOR_FUNC(nbits) \ From 70024b6b47b9eacfe01e8f92349ca9bf1ccd7d5a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 21 Oct 2021 13:25:59 +0200 Subject: [PATCH 022/894] avcodec/flac_parser: Consider AV_INPUT_BUFFER_PADDING_SIZE Fixes: out if array read Fixes: 40109/clusterfuzz-testcase-minimized-ffmpeg_dem_FLAC_fuzzer-4805686811295744 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Mattias Wadman Signed-off-by: Michael Niedermayer --- libavcodec/flac_parser.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index 2c550507fc..3b27b152fc 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -55,6 +55,7 @@ /** largest possible size of flac header */ #define MAX_FRAME_HEADER_SIZE 16 +#define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1) typedef struct FLACHeaderMarker { int offset; /**< byte offset from start of FLACParseContext->buffer */ @@ -99,7 +100,7 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, uint8_t subframe_type; // header plus one byte from first subframe - init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8 + 8); + init_get_bits(&gb, buf, MAX_FRAME_VERIFY_SIZE * 8); if (ff_flac_decode_frame_header(avctx, &gb, fi, 127)) { return 0; } @@ -196,7 +197,7 @@ static int find_headers_search_validate(FLACParseContext *fpc, int offset) uint8_t *header_buf; int size = 0; header_buf = flac_fifo_read_wrap(fpc, offset, - MAX_FRAME_HEADER_SIZE, + MAX_FRAME_VERIFY_SIZE + AV_INPUT_BUFFER_PADDING_SIZE, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); if (frame_header_is_valid(fpc->avctx, header_buf, &fi)) { From 9e8bb9efd9f06d6bb879f0c07dd48ea5c33ac376 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Oct 2021 14:15:24 +0200 Subject: [PATCH 023/894] avfilter/vf_convolution: unbreak runtime planes option functionality For non-convolution filters like sobel. --- libavfilter/vf_convolution.c | 210 ++++++++++++++++------------------- 1 file changed, 96 insertions(+), 114 deletions(-) diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index cc9ba2399e..47b59de421 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -699,96 +699,12 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) return 0; } -static int config_input(AVFilterLink *inlink) +static int param_init(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; ConvolutionContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int p; - - s->depth = desc->comp[0].depth; - s->max = (1 << s->depth) - 1; - - s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); - s->planewidth[0] = s->planewidth[3] = inlink->w; - s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); - s->planeheight[0] = s->planeheight[3] = inlink->h; - - s->nb_planes = av_pix_fmt_count_planes(inlink->format); - s->nb_threads = ff_filter_get_nb_threads(ctx); - s->bpc = (s->depth + 7) / 8; - - if (!strcmp(ctx->filter->name, "convolution")) { - if (s->depth > 8) { - for (p = 0; p < s->nb_planes; p++) { - if (s->mode[p] == MATRIX_ROW) - s->filter[p] = filter16_row; - else if (s->mode[p] == MATRIX_COLUMN) - s->filter[p] = filter16_column; - else if (s->size[p] == 3) - s->filter[p] = filter16_3x3; - else if (s->size[p] == 5) - s->filter[p] = filter16_5x5; - else if (s->size[p] == 7) - s->filter[p] = filter16_7x7; - } - } -#if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64 - ff_convolution_init_x86(s); -#endif - } else if (!strcmp(ctx->filter->name, "prewitt")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_prewitt; - } else if (!strcmp(ctx->filter->name, "roberts")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_roberts; - } else if (!strcmp(ctx->filter->name, "sobel")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_sobel; - } else if (!strcmp(ctx->filter->name, "kirsch")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_kirsch; - } else if (!strcmp(ctx->filter->name, "scharr")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_scharr; - } - - return 0; -} - -static int filter_frame(AVFilterLink *inlink, AVFrame *in) -{ - AVFilterContext *ctx = inlink->dst; - ConvolutionContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out; - ThreadData td; - - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - av_frame_copy_props(out, in); - - td.in = in; - td.out = out; - ff_filter_execute(ctx, filter_slice, &td, NULL, - FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads)); - - av_frame_free(&in); - return ff_filter_frame(outlink, out); -} - -static av_cold int init(AVFilterContext *ctx) -{ - ConvolutionContext *s = ctx->priv; - int i; + int p, i; if (!strcmp(ctx->filter->name, "convolution")) { for (i = 0; i < 4; i++) { @@ -866,10 +782,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "prewitt")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_prewitt; - else - s->copy[i] = 1; + s->filter[i] = filter_prewitt; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -877,10 +791,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "roberts")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_roberts; - else - s->copy[i] = 1; + s->filter[i] = filter_roberts; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -888,10 +800,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "sobel")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_sobel; - else - s->copy[i] = 1; + s->filter[i] = filter_sobel; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -899,10 +809,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "kirsch")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_kirsch; - else - s->copy[i] = 1; + s->filter[i] = filter_kirsch; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -910,10 +818,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "scharr")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_scharr; - else - s->copy[i] = 1; + s->filter[i] = filter_scharr; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -921,9 +827,91 @@ static av_cold int init(AVFilterContext *ctx) } } + s->depth = desc->comp[0].depth; + s->max = (1 << s->depth) - 1; + + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + s->nb_threads = ff_filter_get_nb_threads(ctx); + s->bpc = (s->depth + 7) / 8; + + if (!strcmp(ctx->filter->name, "convolution")) { + if (s->depth > 8) { + for (p = 0; p < s->nb_planes; p++) { + if (s->mode[p] == MATRIX_ROW) + s->filter[p] = filter16_row; + else if (s->mode[p] == MATRIX_COLUMN) + s->filter[p] = filter16_column; + else if (s->size[p] == 3) + s->filter[p] = filter16_3x3; + else if (s->size[p] == 5) + s->filter[p] = filter16_5x5; + else if (s->size[p] == 7) + s->filter[p] = filter16_7x7; + } + } +#if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64 + ff_convolution_init_x86(s); +#endif + } else if (!strcmp(ctx->filter->name, "prewitt")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_prewitt; + } else if (!strcmp(ctx->filter->name, "roberts")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_roberts; + } else if (!strcmp(ctx->filter->name, "sobel")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_sobel; + } else if (!strcmp(ctx->filter->name, "kirsch")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_kirsch; + } else if (!strcmp(ctx->filter->name, "scharr")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_scharr; + } + return 0; } +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + return param_init(ctx); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ConvolutionContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + ThreadData td; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + + td.in = in; + td.out = out; + ff_filter_execute(ctx, filter_slice, &td, NULL, + FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads)); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags) { @@ -933,7 +921,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar if (ret < 0) return ret; - return init(ctx); + return param_init(ctx); } static const AVFilterPad convolution_inputs[] = { @@ -959,7 +947,6 @@ const AVFilter ff_vf_convolution = { .description = NULL_IF_CONFIG_SMALL("Apply convolution filter."), .priv_size = sizeof(ConvolutionContext), .priv_class = &convolution_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -986,7 +973,6 @@ const AVFilter ff_vf_prewitt = { .description = NULL_IF_CONFIG_SMALL("Apply prewitt operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1003,7 +989,6 @@ const AVFilter ff_vf_sobel = { .description = NULL_IF_CONFIG_SMALL("Apply sobel operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1020,7 +1005,6 @@ const AVFilter ff_vf_roberts = { .description = NULL_IF_CONFIG_SMALL("Apply roberts cross operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1037,7 +1021,6 @@ const AVFilter ff_vf_kirsch = { .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1054,7 +1037,6 @@ const AVFilter ff_vf_scharr = { .description = NULL_IF_CONFIG_SMALL("Apply scharr operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), From 6c45d34e505f7ef93e07db4a616e7b98d1490102 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Oct 2021 14:47:11 +0200 Subject: [PATCH 024/894] avfilter/vf_convolution: improve runtime support for convolution filter --- libavfilter/vf_convolution.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index 47b59de421..6e6fe0d887 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -709,12 +709,14 @@ static int param_init(AVFilterContext *ctx) if (!strcmp(ctx->filter->name, "convolution")) { for (i = 0; i < 4; i++) { int *matrix = (int *)s->matrix[i]; - char *p, *arg, *saveptr = NULL; - float sum = 0; + char *orig, *p, *arg, *saveptr = NULL; + float sum = 1.f; - p = s->matrix_str[i]; + p = orig = av_strdup(s->matrix_str[i]); if (p) { s->matrix_length[i] = 0; + s->rdiv[i] = 0.f; + sum = 0.f; while (s->matrix_length[i] < 49) { if (!(arg = av_strtok(p, " |", &saveptr))) @@ -726,6 +728,7 @@ static int param_init(AVFilterContext *ctx) s->matrix_length[i]++; } + av_freep(&orig); if (!(s->matrix_length[i] & 1)) { av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n"); return AVERROR(EINVAL); From a586ce0a21a29503e318479aa965fdb3eb5d98f7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Oct 2021 16:59:38 +0200 Subject: [PATCH 025/894] avfilter/vf_dblur: fix artifacts --- libavfilter/vf_dblur.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c index 8ea1229629..48c21c81b6 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -68,7 +68,7 @@ static int filter_horizontally(AVFilterContext *ctx, int width, int height) if (s->R3 > 0) { for (int y = 1; y < height - 1; y++) { - g = q * f(0, 0) + c * f(0, 0); + g = q * f(y, 0) + c * f(y, 0); for (int x = 0; x < width; x++) { f(y, x) = b0 * f(y, x) + b1 * f(y - 1, x) + g; g = q * f(y, x) + c * f(y - 1, x); @@ -84,7 +84,7 @@ static int filter_horizontally(AVFilterContext *ctx, int width, int height) } } else { for (int y = 1; y < height - 1; y++) { - g = q * f(0, width - 1) + c * f(0, width - 1); + g = q * f(y, width - 1) + c * f(y, width - 1); for (int x = width - 1; x >= 0; x--) { f(y, x) = b0 * f(y, x) + b1 * f(y - 1, x) + g; g = q * f(y, x) + c * f(y - 1, x); From 2148934ce3145940419ccc5b2d7ae93d11a043aa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Oct 2021 20:31:24 +0200 Subject: [PATCH 026/894] avfilter/vf_dblur: use lrintf() --- libavfilter/vf_dblur.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c index 48c21c81b6..c1e20fef6c 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -241,7 +241,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->depth == 8) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - dst[x] = bptr[x]; + dst[x] = lrintf(bptr[x]); } bptr += width; dst += out->linesize[plane]; @@ -249,7 +249,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } else { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - dst16[x] = bptr[x]; + dst16[x] = lrintf(bptr[x]); } bptr += width; dst16 += out->linesize[plane] / 2; From 97cff84f106ff348a48915866ba7f487a77f2c31 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Oct 2021 23:51:42 +0200 Subject: [PATCH 027/894] avfilter/vf_dblur: add clipping --- libavfilter/vf_dblur.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c index c1e20fef6c..e821029906 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -241,7 +241,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->depth == 8) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - dst[x] = lrintf(bptr[x]); + dst[x] = av_clip_uint8(lrintf(bptr[x])); } bptr += width; dst += out->linesize[plane]; @@ -249,7 +249,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } else { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - dst16[x] = lrintf(bptr[x]); + dst16[x] = av_clip_uintp2_c(lrintf(bptr[x]), s->depth); } bptr += width; dst16 += out->linesize[plane] / 2; From d39b58dc32b5fc7b480eeb9ef00a610732f02c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Wed, 13 Oct 2021 22:21:51 +0300 Subject: [PATCH 028/894] avformat/avio: privatize source of truth for AVIOContext::written Looking at 3f75e5116b900f1428aa13041fc7d6301bf1988a, the field was supposed to be private, but during merging the field and the group that had the comment about it got separated. Thus, move the actual privately utilized state of this variable into the private FFIOContext. Additionally, name the private field somewhat better, so that it does not get confused with the amount of bytes written out. --- libavformat/avio_internal.h | 6 ++++++ libavformat/aviobuf.c | 11 +++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index eded38759b..467e80701f 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -66,6 +66,12 @@ typedef struct FFIOContext { * used after probing to ensure seekback and to reset the buffer size */ int orig_buffer_size; + + /** + * Written output size + * is updated each time a successful writeout ends up further position-wise + */ + int64_t written_output_size; } FFIOContext; static av_always_inline FFIOContext *ffiocontext(AVIOContext *ctx) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 3d87d66091..b18a56ef19 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -164,8 +164,10 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len) if (ret < 0) { s->error = ret; } else { - if (s->pos + len > s->written) - s->written = s->pos + len; + if (s->pos + len > ctx->written_output_size) { + ctx->written_output_size = s->pos + len; + s->written = ctx->written_output_size; + } } } if (ctx->current_type == AVIO_DATA_MARKER_SYNC_POINT || @@ -337,13 +339,14 @@ int64_t avio_skip(AVIOContext *s, int64_t offset) int64_t avio_size(AVIOContext *s) { + FFIOContext *const ctx = ffiocontext(s); int64_t size; if (!s) return AVERROR(EINVAL); - if (s->written) - return s->written; + if (ctx->written_output_size) + return ctx->written_output_size; if (!s->seek) return AVERROR(ENOSYS); From a5622ed16f8e22a80cecd8936799e61f61a74cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Wed, 13 Oct 2021 23:05:40 +0300 Subject: [PATCH 029/894] avformat/avio{,buf}: deprecate AVIOContext::written Originally added as a private entry in commit 3f75e5116b900f1428aa13041fc7d6301bf1988a, but its grouping with the comment noting its private state was missed during merging of the field from Libav (most likely due to an already existing field in between). --- doc/APIchanges | 6 ++++++ libavformat/avio.h | 6 ++++++ libavformat/aviobuf.c | 9 +++++++++ libavformat/version.h | 5 ++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 7b267a79ac..4731e14cb1 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,12 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-10-13 - xxxxxxxxxx - lavf 59.7.100 - avio.h + Deprecate AVIOContext.written. Originally added as a private entry in + commit 3f75e5116b900f1428aa13041fc7d6301bf1988a, its grouping with + the comment noting its private state was missed during merging of the field + from Libav (most likely due to an already existing field in between). + 2021-09-21 - xxxxxxxxxx - lavu 57.7.100 - pixfmt.h Add AV_PIX_FMT_X2BGR10. diff --git a/libavformat/avio.h b/libavformat/avio.h index a7b56ab667..5e60c2e35c 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -290,7 +290,13 @@ typedef struct AVIOContext { */ int ignore_boundary_point; +#if FF_API_AVIOCONTEXT_WRITTEN + /** + * @deprecated field utilized privately by libavformat. + */ + attribute_deprecated int64_t written; +#endif /** * Maximum reached position before a backward seek in the write buffer, diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index b18a56ef19..f21f1c89df 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -22,6 +22,7 @@ #include "libavutil/bprint.h" #include "libavutil/crc.h" #include "libavutil/dict.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -124,7 +125,11 @@ void ffio_init_context(FFIOContext *ctx, ctx->current_type = AVIO_DATA_MARKER_UNKNOWN; ctx->last_time = AV_NOPTS_VALUE; ctx->short_seek_get = NULL; +#if FF_API_AVIOCONTEXT_WRITTEN +FF_DISABLE_DEPRECATION_WARNINGS s->written = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } AVIOContext *avio_alloc_context( @@ -166,7 +171,11 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len) } else { if (s->pos + len > ctx->written_output_size) { ctx->written_output_size = s->pos + len; +#if FF_API_AVIOCONTEXT_WRITTEN +FF_DISABLE_DEPRECATION_WARNINGS s->written = ctx->written_output_size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } } diff --git a/libavformat/version.h b/libavformat/version.h index d5dd22059b..de780124c7 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 6 +#define LIBAVFORMAT_VERSION_MINOR 7 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -61,6 +61,9 @@ #ifndef FF_API_COMPUTE_PKT_FIELDS2 #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) #endif +#ifndef FF_API_AVIOCONTEXT_WRITTEN +#define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) +#endif #ifndef FF_API_R_FRAME_RATE From 682bafdb12507ec8b049ecbbe2e48bf814927002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Mon, 18 Oct 2021 00:35:48 +0300 Subject: [PATCH 030/894] avformat/avio{,buf}: introduce public AVIOContext::bytes_{read,written} Such fields can be seen as generally useful in cases where the API user is not implementing custom AVIO callbacks, but still would like to know if data is being read or written out, such as in case data is being read from input but no AVPacket has been received yet. --- doc/APIchanges | 3 +++ libavformat/avio.h | 14 +++++++++++++- libavformat/avio_internal.h | 5 +++++ libavformat/aviobuf.c | 10 ++++++++-- libavformat/version.h | 2 +- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4731e14cb1..99e185ee4e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-10-18 - xxxxxxxxxx - lavf 59.8.100 - avio.h + Introduce public bytes_{read,written} statistic fields to AVIOContext. + 2021-10-13 - xxxxxxxxxx - lavf 59.7.100 - avio.h Deprecate AVIOContext.written. Originally added as a private entry in commit 3f75e5116b900f1428aa13041fc7d6301bf1988a, its grouping with diff --git a/libavformat/avio.h b/libavformat/avio.h index 5e60c2e35c..cd63322a62 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -292,7 +292,9 @@ typedef struct AVIOContext { #if FF_API_AVIOCONTEXT_WRITTEN /** - * @deprecated field utilized privately by libavformat. + * @deprecated field utilized privately by libavformat. For a public + * statistic of how many bytes were written out, see + * AVIOContext::bytes_written. */ attribute_deprecated int64_t written; @@ -303,6 +305,16 @@ typedef struct AVIOContext { * used keeping track of already written data for a later flush. */ unsigned char *buf_ptr_max; + + /** + * Read-only statistic of bytes read for this AVIOContext. + */ + int64_t bytes_read; + + /** + * Read-only statistic of bytes written for this AVIOContext. + */ + int64_t bytes_written; } AVIOContext; /** diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 467e80701f..187433f283 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -51,6 +51,11 @@ typedef struct FFIOContext { */ int64_t bytes_read; + /** + * Bytes written statistic + */ + int64_t bytes_written; + /** * seek statistic */ diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index f21f1c89df..5da4dea7b6 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -169,6 +169,9 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len) if (ret < 0) { s->error = ret; } else { + ctx->bytes_written += len; + s->bytes_written = ctx->bytes_written; + if (s->pos + len > ctx->written_output_size) { ctx->written_output_size = s->pos + len; #if FF_API_AVIOCONTEXT_WRITTEN @@ -584,6 +587,7 @@ static void fill_buffer(AVIOContext *s) s->buf_ptr = dst; s->buf_end = dst + len; ffiocontext(s)->bytes_read += len; + s->bytes_read = ffiocontext(s)->bytes_read; } } @@ -657,6 +661,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) } else { s->pos += len; ffiocontext(s)->bytes_read += len; + s->bytes_read = ffiocontext(s)->bytes_read; size -= len; buf += len; // reset the buffer @@ -1236,8 +1241,9 @@ int avio_close(AVIOContext *s) av_freep(&s->buffer); if (s->write_flag) - av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n", - ctx->seek_count, ctx->writeout_count); + av_log(s, AV_LOG_VERBOSE, + "Statistics: %"PRId64" bytes written, %d seeks, %d writeouts\n", + ctx->bytes_written, ctx->seek_count, ctx->writeout_count); else av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n", ctx->bytes_read, ctx->seek_count); diff --git a/libavformat/version.h b/libavformat/version.h index de780124c7..81ed517609 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 7 +#define LIBAVFORMAT_VERSION_MINOR 8 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 9353d1a60ffbb1031ba36c0a53d0e2085389b601 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:00:49 +0200 Subject: [PATCH 031/894] avfilter/vf_v360: replace deprecated FF_CEIL_RSHIFT() --- libavfilter/vf_v360.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index c252a2057a..8a27e0fab2 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -4254,9 +4254,9 @@ static void fov_from_dfov(int format, float d_fov, float w, float h, float *h_fo static void set_dimensions(int *outw, int *outh, int w, int h, const AVPixFmtDescriptor *desc) { - outw[1] = outw[2] = FF_CEIL_RSHIFT(w, desc->log2_chroma_w); + outw[1] = outw[2] = AV_CEIL_RSHIFT(w, desc->log2_chroma_w); outw[0] = outw[3] = w; - outh[1] = outh[2] = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); + outh[1] = outh[2] = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); outh[0] = outh[3] = h; } From 9df3f147f5a1c11230f3b82fed9524a3ad14a7ae Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:05:28 +0200 Subject: [PATCH 032/894] avfilter/vf_v360: do not reset yaw/pitch/roll with reset_rot true --- libavfilter/vf_v360.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index 8a27e0fab2..5df273d375 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -4961,7 +4961,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar V360Context *s = ctx->priv; int ret; - s->yaw = s->pitch = s->roll = 0.f; + if (s->reset_rot <= 0) + s->yaw = s->pitch = s->roll = 0.f; if (s->reset_rot < 0) s->reset_rot = 0; From c7699f95bb00cd7835aca4452d83320e42550a1d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 22 Oct 2021 23:15:59 +0200 Subject: [PATCH 033/894] swscale/utils: Set all threads to the same colorspace even on failure Fixes: ./ffplay dav.y4m -vf "scale=hd1080:threads=4" Found-by: Paul Signed-off-by: Michael Niedermayer --- libswscale/utils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index 367b0ea501..3752c3ec38 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -874,15 +874,16 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int need_reinit = 0; if (c->nb_slice_ctx) { + int parent_ret = 0; for (int i = 0; i < c->nb_slice_ctx; i++) { int ret = sws_setColorspaceDetails(c->slice_ctx[i], inv_table, srcRange, table, dstRange, brightness, contrast, saturation); if (ret < 0) - return ret; + parent_ret = ret; } - return 0; + return parent_ret; } handle_formats(c); From 5f3a160b422e87e17d8fcd3aea51d478d0f05ba5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 22 Oct 2021 23:24:11 +0200 Subject: [PATCH 034/894] swscale/utils: Improve return codes of sws_setColorspaceDetails() Signed-off-by: Michael Niedermayer --- libswscale/utils.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index 3752c3ec38..c726922527 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -995,7 +995,10 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], 0, 1 << 16, 1 << 16); return 0; } - return -1; + //We do not support this combination currently, we need to cascade more contexts to compensate + if (c->cascaded_context[0] && memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4)) + return -1; //AVERROR_PATCHWELCOME; + return 0; } if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) { From 8316b2a15f5e3c0f8da43fa1e43bb5717b56b48a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 23 Oct 2021 10:06:09 +0200 Subject: [PATCH 035/894] swscale/swscale: Improve *ColorspaceDetails() doxy Signed-off-by: Michael Niedermayer --- libswscale/swscale.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 59610d0342..daa53dc01e 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -318,14 +318,22 @@ unsigned int sws_receive_slice_alignment(const struct SwsContext *c); * @param brightness 16.16 fixed point brightness correction * @param contrast 16.16 fixed point contrast correction * @param saturation 16.16 fixed point saturation correction +#if LIBSWSCALE_VERSION_MAJOR > 6 + * @return negative error code on error, non negative otherwise +#else * @return -1 if not supported +#endif */ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation); /** +#if LIBSWSCALE_VERSION_MAJOR > 6 + * @return negative error code on error, non negative otherwise +#else * @return -1 if not supported +#endif */ int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, From 069f7831a2bd1545080121fb6d0773191cd61d70 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 23 Oct 2021 15:24:37 +0200 Subject: [PATCH 036/894] avfilter/vf_owdenoise: relicense my code Signed-off-by: Michael Niedermayer --- libavfilter/vf_owdenoise.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/vf_owdenoise.c b/libavfilter/vf_owdenoise.c index f15baf7e08..bb99e8f33c 100644 --- a/libavfilter/vf_owdenoise.c +++ b/libavfilter/vf_owdenoise.c @@ -19,6 +19,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +// The code written by Michael Niedermayer in 70024b6b47b9eacfe01e8f92349ca9bf1ccd7d5a:libavfilter/vf_owdenoise.c +// can also be used under the LGPL due to: +// durandal_1707, if you do all the "todo" points from vf_owdenoise.c that are in that file since 2013 then sure i would be more than happy to relicense my part of it to LGPL +// michaelni: first relicense than work + /** * @todo try to change to int * @todo try lifting based implementation From 97b5b9dbea2fd51861218416dafc46984e286826 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 26 Oct 2021 12:34:30 +0200 Subject: [PATCH 037/894] avfilter: split negate filter from lut filter Using luts for negating is suboptimal. FATE test changes because filter no longer clips values into limited color range. --- doc/filters.texi | 13 ++ libavfilter/Makefile | 2 +- libavfilter/vf_lut.c | 28 --- libavfilter/vf_negate.c | 375 +++++++++++++++++++++++++++++++++++ tests/ref/fate/filter-negate | 100 +++++----- 5 files changed, 439 insertions(+), 79 deletions(-) create mode 100644 libavfilter/vf_negate.c diff --git a/doc/filters.texi b/doc/filters.texi index 93eadda45d..90e805279c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -15551,6 +15551,19 @@ Negate (invert) the input video. It accepts the following option: @table @option +@item components +Set components to negate. + +Available values for components are: +@table @samp +@item y +@item u +@item v +@item a +@item r +@item g +@item b +@end table @item negate_alpha With value 1, it negates the alpha component, if present. Default value is 0. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 94772576b1..e24f419834 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -350,7 +350,7 @@ OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o framesync.o OBJS-$(CONFIG_MONOCHROME_FILTER) += vf_monochrome.o OBJS-$(CONFIG_MORPHO_FILTER) += vf_morpho.o OBJS-$(CONFIG_MPDECIMATE_FILTER) += vf_mpdecimate.o -OBJS-$(CONFIG_NEGATE_FILTER) += vf_lut.o +OBJS-$(CONFIG_NEGATE_FILTER) += vf_negate.o OBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o OBJS-$(CONFIG_NLMEANS_OPENCL_FILTER) += vf_nlmeans_opencl.o opencl.o opencl/nlmeans.o OBJS-$(CONFIG_NNEDI_FILTER) += vf_nnedi.o diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index 64668039d1..fd5b364797 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -69,7 +69,6 @@ typedef struct LutContext { int is_planar; int is_16bit; int step; - int negate_alpha; /* only used by negate */ } LutContext; #define Y 0 @@ -642,30 +641,3 @@ static av_cold int lutrgb_init(AVFilterContext *ctx) DEFINE_LUT_FILTER(lutrgb, "Compute and apply a lookup table to the RGB input video.", lut); #endif - -#if CONFIG_NEGATE_FILTER - -static const AVOption negate_options[] = { - { "negate_alpha", NULL, OFFSET(negate_alpha), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, - { NULL } -}; - -AVFILTER_DEFINE_CLASS(negate); - -static av_cold int negate_init(AVFilterContext *ctx) -{ - LutContext *s = ctx->priv; - - for (int i = 0; i < 4; i++) { - s->comp_expr_str[i] = av_strdup((i == 3 && !s->negate_alpha) ? - "val" : "negval"); - if (!s->comp_expr_str[i]) - return AVERROR(ENOMEM); - } - - return 0; -} - -DEFINE_LUT_FILTER(negate, "Negate input video.", negate); - -#endif diff --git a/libavfilter/vf_negate.c b/libavfilter/vf_negate.c new file mode 100644 index 0000000000..d782e63d3a --- /dev/null +++ b/libavfilter/vf_negate.c @@ -0,0 +1,375 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +#define COMP_R 0x01 +#define COMP_G 0x02 +#define COMP_B 0x04 +#define COMP_A 0x08 +#define COMP_Y 0x10 +#define COMP_U 0x20 +#define COMP_V 0x40 + +typedef struct ThreadData { + AVFrame *in; + AVFrame *out; +} ThreadData; + +typedef struct NegateContext { + const AVClass *class; + int negate_alpha; + int max; + int requested_components; + int components; + int planes; + int step; + int nb_planes; + int linesize[4]; + int width[4]; + int height[4]; + uint8_t rgba_map[4]; + + void (*negate)(const uint8_t *src, uint8_t *dst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components); +} NegateContext; + +#define OFFSET(x) offsetof(NegateContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption negate_options[] = { + { "components", "set components to negate", OFFSET(requested_components), AV_OPT_TYPE_FLAGS, {.i64=0x77}, 1, 0xff, FLAGS, "flags"}, + { "y", "set luma component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_Y}, 0, 0, FLAGS, "flags"}, + { "u", "set u component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_U}, 0, 0, FLAGS, "flags"}, + { "v", "set v component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_V}, 0, 0, FLAGS, "flags"}, + { "r", "set red component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_R}, 0, 0, FLAGS, "flags"}, + { "g", "set green component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_G}, 0, 0, FLAGS, "flags"}, + { "b", "set blue component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_B}, 0, 0, FLAGS, "flags"}, + { "a", "set alpha component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_A}, 0, 0, FLAGS, "flags"}, + { "negate_alpha", NULL, OFFSET(negate_alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(negate); + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, + AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_ARGB, AV_PIX_FMT_RGBA, + AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, + AV_PIX_FMT_BGR48, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRAP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP12, + AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE +}; + +static void negate8(const uint8_t *src, uint8_t *dst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + dst[x] = 255 - src[x]; + + dst += dlinesize; + src += slinesize; + } +} + +static void negate_packed8(const uint8_t *ssrc, uint8_t *ddst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + for (int y = 0; y < h; y++) { + const uint8_t *src = ssrc + y * slinesize; + uint8_t *dst = ddst + y * dlinesize; + + for (int x = 0; x < w; x++) { + switch (step) { + case 4: dst[3] = components & 8 ? 255 - src[3] : src[3]; + case 3: dst[2] = components & 4 ? 255 - src[2] : src[2]; + case 2: dst[1] = components & 2 ? 255 - src[1] : src[1]; + default: dst[0] = components & 1 ? 255 - src[0] : src[0]; + } + + src += step; + dst += step; + } + } +} + +static void negate16(const uint8_t *ssrc, uint8_t *ddst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + const uint16_t *src = (const uint16_t *)ssrc; + uint16_t *dst = (uint16_t *)ddst; + + dlinesize /= 2; + slinesize /= 2; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + dst[x] = max - src[x]; + + dst += dlinesize; + src += slinesize; + } +} + +static void negate_packed16(const uint8_t *ssrc, uint8_t *ddst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + for (int y = 0; y < h; y++) { + const uint16_t *src = (const uint16_t *)(ssrc + y * slinesize); + uint16_t *dst = (uint16_t *)(ddst + y * dlinesize); + + for (int x = 0; x < w; x++) { + switch (step) { + case 4: dst[3] = components & 8 ? max - src[3] : src[3]; + case 3: dst[2] = components & 4 ? max - src[2] : src[2]; + case 2: dst[1] = components & 2 ? max - src[1] : src[1]; + default: dst[0] = components & 1 ? max - src[0] : src[0]; + } + + src += step; + dst += step; + } + } +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + NegateContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int depth, vsub, hsub, ret, is_packed; + int comp_avail; + + s->planes = s->negate_alpha ? 0xF : 0x7; + is_packed = !(desc->flags & AV_PIX_FMT_FLAG_PLANAR) && + (desc->nb_components > 1); + if (s->requested_components != 0x77) { + comp_avail = ((desc->flags & AV_PIX_FMT_FLAG_RGB) ? COMP_R|COMP_G|COMP_B : + COMP_Y | + ((desc->nb_components > 2) ? COMP_U|COMP_V : 0)) | + ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? COMP_A : 0); + if (s->requested_components & ~comp_avail) { + av_log(ctx, AV_LOG_ERROR, "Requested components not available.\n"); + return AVERROR(EINVAL); + } + + s->planes = 0; + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) { + if (s->requested_components & COMP_Y) + s->planes |= 1; + if (s->requested_components & COMP_U) + s->planes |= 2; + if (s->requested_components & COMP_V) + s->planes |= 4; + if (s->requested_components & COMP_A) + s->planes |= 8; + } else { + if (s->requested_components & COMP_R) + s->planes |= 4; + if (s->requested_components & COMP_G) + s->planes |= 1; + if (s->requested_components & COMP_B) + s->planes |= 2; + if (s->requested_components & COMP_A) + s->planes |= 8; + } + } + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + s->components = 0; + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + ff_fill_rgba_map(s->rgba_map, inlink->format); + + if (s->requested_components & COMP_R) + s->components |= 1 << s->rgba_map[0]; + if (s->requested_components & COMP_G) + s->components |= 1 << s->rgba_map[1]; + if (s->requested_components & COMP_B) + s->components |= 1 << s->rgba_map[2]; + if (s->requested_components & COMP_A) + s->components |= 1 << s->rgba_map[3]; + } + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + depth = desc->comp[0].depth; + hsub = desc->log2_chroma_w; + vsub = desc->log2_chroma_h; + s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + s->height[0] = s->height[3] = inlink->h; + s->width[1] = s->width[2] = AV_CEIL_RSHIFT(inlink->w, hsub); + s->width[0] = s->width[3] = inlink->w; + + s->negate = depth <= 8 ? negate8 : negate16; + if (is_packed) { + s->negate = depth <= 8 ? negate_packed8 : negate_packed16; + s->planes = 1; + } + s->max = (1 << depth) - 1; + s->step = av_get_bits_per_pixel(desc) >> 3; + if (depth > 8) + s->step = s->step >> 1; + + return 0; +} + +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + NegateContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + for (int p = 0; p < s->nb_planes; p++) { + const int h = s->height[p]; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + + if (!((1 << p) & s->planes)) { + if (out != in) + av_image_copy_plane(out->data[p] + slice_start * out->linesize[p], + out->linesize[p], + in->data[p] + slice_start * in->linesize[p], + in->linesize[p], + s->linesize[p], slice_end - slice_start); + continue; + } + + s->negate(in->data[p] + slice_start * in->linesize[p], + out->data[p] + slice_start * out->linesize[p], + in->linesize[p], out->linesize[p], + s->width[p], slice_end - slice_start, + s->max, s->step, s->components); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + NegateContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + td.out = out; + td.in = in; + ff_filter_execute(ctx, filter_slice, &td, NULL, + FFMIN(s->height[2], ff_filter_get_nb_threads(ctx))); + if (out != in) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + NegateContext *s = ctx->priv; + int old_planes = s->planes; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = config_input(ctx->inputs[0]); + if (ret < 0) + s->planes = old_planes; + return ret; +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_negate = { + .name = "negate", + .description = NULL_IF_CONFIG_SMALL("Negate input video."), + .priv_size = sizeof(NegateContext), + .priv_class = &negate_class, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_PIXFMTS_ARRAY(pix_fmts), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; diff --git a/tests/ref/fate/filter-negate b/tests/ref/fate/filter-negate index 88d04718ae..aa9a820c0d 100644 --- a/tests/ref/fate/filter-negate +++ b/tests/ref/fate/filter-negate @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xef20e1ec -0, 1, 1, 1, 152064, 0x899606ec -0, 2, 2, 1, 152064, 0xaea175d2 -0, 3, 3, 1, 152064, 0x5201eb55 -0, 4, 4, 1, 152064, 0xf02bb525 -0, 5, 5, 1, 152064, 0x99fdc305 -0, 6, 6, 1, 152064, 0x3a8fefe7 -0, 7, 7, 1, 152064, 0x005edfbf -0, 8, 8, 1, 152064, 0xe37aea50 -0, 9, 9, 1, 152064, 0xa5ad32f9 -0, 10, 10, 1, 152064, 0xb1e52485 -0, 11, 11, 1, 152064, 0x55b06e56 -0, 12, 12, 1, 152064, 0xdfb7be97 -0, 13, 13, 1, 152064, 0x191bca13 -0, 14, 14, 1, 152064, 0xa554dd3c -0, 15, 15, 1, 152064, 0x36075b77 -0, 16, 16, 1, 152064, 0xbf6b1cbd -0, 17, 17, 1, 152064, 0xf33432b6 -0, 18, 18, 1, 152064, 0x5d7100c3 -0, 19, 19, 1, 152064, 0x376f8f0c -0, 20, 20, 1, 152064, 0x07ca75fa -0, 21, 21, 1, 152064, 0xe3984704 -0, 22, 22, 1, 152064, 0xa8fb4e4c -0, 23, 23, 1, 152064, 0xe8e102d8 -0, 24, 24, 1, 152064, 0xcc6771c9 -0, 25, 25, 1, 152064, 0xf646d238 -0, 26, 26, 1, 152064, 0xa52cd41e -0, 27, 27, 1, 152064, 0x536d92c2 -0, 28, 28, 1, 152064, 0x7058c6a1 -0, 29, 29, 1, 152064, 0xcc6c05d0 -0, 30, 30, 1, 152064, 0x1fc2ffb8 -0, 31, 31, 1, 152064, 0x041ea59c -0, 32, 32, 1, 152064, 0xfc006e07 -0, 33, 33, 1, 152064, 0x0246efe1 -0, 34, 34, 1, 152064, 0x079428e5 -0, 35, 35, 1, 152064, 0x64d9d773 -0, 36, 36, 1, 152064, 0x914d3454 -0, 37, 37, 1, 152064, 0xef69686e -0, 38, 38, 1, 152064, 0x3c91129f -0, 39, 39, 1, 152064, 0x2a611ca7 -0, 40, 40, 1, 152064, 0xaf56124f -0, 41, 41, 1, 152064, 0xce48cd45 -0, 42, 42, 1, 152064, 0x75feac29 -0, 43, 43, 1, 152064, 0xfd2b4b5b -0, 44, 44, 1, 152064, 0x8d2f675c -0, 45, 45, 1, 152064, 0x1573ed3b -0, 46, 46, 1, 152064, 0xb0fc17ca -0, 47, 47, 1, 152064, 0x53e5a654 -0, 48, 48, 1, 152064, 0xe0cbb786 -0, 49, 49, 1, 152064, 0xcaa092fe +0, 0, 0, 1, 152064, 0xdb0946b2 +0, 1, 1, 1, 152064, 0x950c6b50 +0, 2, 2, 1, 152064, 0x42e3da48 +0, 3, 3, 1, 152064, 0xb63d4ff1 +0, 4, 4, 1, 152064, 0x92dd1a4f +0, 5, 5, 1, 152064, 0xf2fc27bb +0, 6, 6, 1, 152064, 0xfea2547e +0, 7, 7, 1, 152064, 0x860b44f5 +0, 8, 8, 1, 152064, 0xc1a5507b +0, 9, 9, 1, 152064, 0x4f89978c +0, 10, 10, 1, 152064, 0xde8c8941 +0, 11, 11, 1, 152064, 0xafcbd3bd +0, 12, 12, 1, 152064, 0x19af2340 +0, 13, 13, 1, 152064, 0xbbd42e7e +0, 14, 14, 1, 152064, 0x8e1c42c4 +0, 15, 15, 1, 152064, 0x37a4c19c +0, 16, 16, 1, 152064, 0x528a8289 +0, 17, 17, 1, 152064, 0x2f6397d9 +0, 18, 18, 1, 152064, 0xee5265d5 +0, 19, 19, 1, 152064, 0xed64f493 +0, 20, 20, 1, 152064, 0xe436db22 +0, 21, 21, 1, 152064, 0x42f9ac8f +0, 22, 22, 1, 152064, 0x9c63b348 +0, 23, 23, 1, 152064, 0xb19967b2 +0, 24, 24, 1, 152064, 0x12b7d6bc +0, 25, 25, 1, 152064, 0x4b69376b +0, 26, 26, 1, 152064, 0x9ce939ec +0, 27, 27, 1, 152064, 0x0940f80b +0, 28, 28, 1, 152064, 0x69ee2c4c +0, 29, 29, 1, 152064, 0x72fd6b93 +0, 30, 30, 1, 152064, 0xd12365d7 +0, 31, 31, 1, 152064, 0xfe1c0b83 +0, 32, 32, 1, 152064, 0x095ad405 +0, 33, 33, 1, 152064, 0xfe825671 +0, 34, 34, 1, 152064, 0x60d68d29 +0, 35, 35, 1, 152064, 0xe6243ba6 +0, 36, 36, 1, 152064, 0x942998f6 +0, 37, 37, 1, 152064, 0x3bb3cea9 +0, 38, 38, 1, 152064, 0xd5b97755 +0, 39, 39, 1, 152064, 0x584d81c4 +0, 40, 40, 1, 152064, 0x0e4d777c +0, 41, 41, 1, 152064, 0x0bdc3299 +0, 42, 42, 1, 152064, 0xbff210f8 +0, 43, 43, 1, 152064, 0x8964afb5 +0, 44, 44, 1, 152064, 0xe361cc30 +0, 45, 45, 1, 152064, 0x7f0c522e +0, 46, 46, 1, 152064, 0xd6d17ca2 +0, 47, 47, 1, 152064, 0x72380adf +0, 48, 48, 1, 152064, 0x25391c1e +0, 49, 49, 1, 152064, 0x9506f7a8 From 148c0303952e6478004a765119e1622b9fb7eb1c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 27 Oct 2021 11:23:37 +0200 Subject: [PATCH 038/894] avfilter/vf_histogram: add more color modes --- doc/filters.texi | 3 +++ libavfilter/vf_histogram.c | 54 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 90e805279c..ae6cb3aafd 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13515,6 +13515,9 @@ It accepts the following values: @item coloronblack @item coloronwhite @item colorongray +@item blackoncolor +@item whiteoncolor +@item grayoncolor @end table Default is @code{whiteonblack}. @end table diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c index fe13cb231b..bf80b2c4fc 100644 --- a/libavfilter/vf_histogram.c +++ b/libavfilter/vf_histogram.c @@ -85,8 +85,8 @@ static const AVOption histogram_options[] = { { "f", "set foreground opacity", OFFSET(fgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.7}, 0, 1, FLAGS}, { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS}, { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS}, - { "colors_mode", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 6, FLAGS, "colors_mode"}, - { "l", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 6, FLAGS, "colors_mode"}, + { "colors_mode", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 9, FLAGS, "colors_mode"}, + { "l", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 9, FLAGS, "colors_mode"}, { "whiteonblack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colors_mode" }, { "blackonwhite", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colors_mode" }, { "whiteongray", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colors_mode" }, @@ -94,6 +94,9 @@ static const AVOption histogram_options[] = { { "coloronblack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "colors_mode" }, { "coloronwhite", NULL, 0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, FLAGS, "colors_mode" }, { "colorongray" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, FLAGS, "colors_mode" }, + { "blackoncolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, FLAGS, "colors_mode" }, + { "whiteoncolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, FLAGS, "colors_mode" }, + { "grayoncolor" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, FLAGS, "colors_mode" }, { NULL } }; @@ -312,6 +315,41 @@ static int config_input(AVFilterLink *inlink) memcpy(s->fg_color[1], blue_yuva_color, 4); memcpy(s->fg_color[2], red_yuva_color, 4); } + } else if (s->colors_mode == 7) { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + FFSWAP(uint8_t, s->fg_color[i][j], s->bg_color[i][j]); + if (rgb) { + memcpy(s->bg_color[0], red_gbrp_color, 4); + memcpy(s->bg_color[1], green_gbrp_color, 4); + memcpy(s->bg_color[2], blue_gbrp_color, 4); + } else { + memcpy(s->bg_color[0], green_yuva_color, 4); + memcpy(s->bg_color[1], blue_yuva_color, 4); + memcpy(s->bg_color[2], red_yuva_color, 4); + } + } else if (s->colors_mode == 8) { + if (rgb) { + memcpy(s->bg_color[0], red_gbrp_color, 4); + memcpy(s->bg_color[1], green_gbrp_color, 4); + memcpy(s->bg_color[2], blue_gbrp_color, 4); + } else { + memcpy(s->bg_color[0], igreen_yuva_color,4); + memcpy(s->bg_color[1], blue_yuva_color, 4); + memcpy(s->bg_color[2], red_yuva_color, 4); + } + } else if (s->colors_mode == 9) { + for (int i = 0; i < 4; i++) + memcpy(s->fg_color[i], gray_color, 4); + if (rgb) { + memcpy(s->bg_color[0], red_gbrp_color, 4); + memcpy(s->bg_color[1], green_gbrp_color, 4); + memcpy(s->bg_color[2], blue_gbrp_color, 4); + } else { + memcpy(s->bg_color[0], igreen_yuva_color,4); + memcpy(s->bg_color[1], blue_yuva_color, 4); + memcpy(s->bg_color[2], red_yuva_color, 4); + } } } @@ -517,6 +555,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out->data[p][(j + starty) * out->linesize[p] + startx + i] = 255; } } + if (s->display_mode) { + for (j = col_height - 1; j >= 0; j--) { + for (l = 0; l < s->dncomp; l++) + out->data[l][(j + starty) * out->linesize[l] + startx + i] = s->bg_color[p][l]; + } + } for (j = s->level_height + s->scale_height - 1; j >= s->level_height; j--) for (l = 0; l < s->dncomp; l++) out->data[l][(j + starty) * out->linesize[l] + startx + i] = p == l ? i : mid; @@ -531,6 +575,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AV_WN16(out->data[p] + (j + starty) * out->linesize[p] + startx * 2 + i * 2, 255 * mult); } } + if (s->display_mode) { + for (j = col_height - 1; j >= 0; j--) { + for (l = 0; l < s->dncomp; l++) + AV_WN16(out->data[l] + (j + starty) * out->linesize[l] + startx * 2 + i * 2, s->bg_color[p][l] * mult); + } + } for (j = s->level_height + s->scale_height - 1; j >= s->level_height; j--) for (l = 0; l < s->dncomp; l++) AV_WN16(out->data[l] + (j + starty) * out->linesize[l] + startx * 2 + i * 2, p == l ? i : mid * mult); From 3c3ef41593821aa8386e4467fb0397e16c928d29 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 14 Oct 2021 19:33:54 +0800 Subject: [PATCH 039/894] avformat/mov: support dvwC box for Dolby Vision By <> Signed-off-by: Limin Wang --- libavformat/mov.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 263d605c41..3fcb1dc908 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -7074,7 +7074,7 @@ static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } - av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, " + av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, " "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", dovi->dv_version_major, dovi->dv_version_minor, dovi->dv_profile, dovi->dv_level, @@ -7273,6 +7273,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('c','l','l','i'), mov_read_clli }, { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc }, { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc }, +{ MKTAG('d','v','w','C'), mov_read_dvcc_dvvc }, { MKTAG('k','i','n','d'), mov_read_kind }, { 0, NULL } }; From c0edfb514bbadd9ce525ed7e1b7ae1cdd65e0df8 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 14 Oct 2021 19:47:32 +0800 Subject: [PATCH 040/894] avformat/movenc: support dvwC box for Dolby Vision By <> Signed-off-by: Limin Wang --- libavformat/movenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index d43a086f4b..37d4403f7a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1912,7 +1912,9 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi) { avio_wb32(pb, 32); /* size = 8 + 24 */ - if (dovi->dv_profile > 7) + if (dovi->dv_profile > 10) + ffio_wfourcc(pb, "dvwC"); + else if (dovi->dv_profile > 7) ffio_wfourcc(pb, "dvvC"); else ffio_wfourcc(pb, "dvcC"); @@ -1926,7 +1928,7 @@ static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDe ffio_fill(pb, 0, 4 * 4); /* reserved */ av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_profile > 7 ? "dvvC" : "dvcC", + dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"), dovi->dv_version_major, dovi->dv_version_minor, dovi->dv_profile, dovi->dv_level, dovi->rpu_present_flag, From 08c688e64dce81d202bf228291eb128eec83a392 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 14 Oct 2021 19:28:57 +0800 Subject: [PATCH 041/894] avformat/mpegts: Fix for the DOVI video stream descriptor By <> Signed-off-by: Limin Wang --- libavformat/mpegts.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index d8cbaa8ced..29a267436f 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -2179,6 +2179,8 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type AVDOVIDecoderConfigurationRecord *dovi; size_t dovi_size; int ret; + int dependency_pid; + if (desc_end - *pp < 4) // (8 + 8 + 7 + 6 + 1 + 1 + 1) / 8 return AVERROR_INVALIDDATA; @@ -2194,7 +2196,11 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit dovi->bl_present_flag = buf & 0x01; // 1 bit - if (desc_end - *pp >= 20) { // 4 + 4 * 4 + if (!dovi->bl_present_flag && desc_end - *pp >= 2) { + buf = get16(pp, desc_end); + dependency_pid = buf >> 3; // 13 bits + } + if (desc_end - *pp >= 1) { // 8 bits buf = get8(pp, desc_end); dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits } else { @@ -2211,12 +2217,13 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } av_log(fc, AV_LOG_TRACE, "DOVI, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + "rpu flag: %d, el flag: %d, bl flag: %d, dependency_pid: %d, compatibility id: %d\n", dovi->dv_version_major, dovi->dv_version_minor, dovi->dv_profile, dovi->dv_level, dovi->rpu_present_flag, dovi->el_present_flag, dovi->bl_present_flag, + dependency_pid, dovi->dv_bl_signal_compatibility_id); } break; From 4e3ffc9c54c26e49076ad4fced7b72ecc5a03945 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 19 Oct 2021 22:46:05 +0800 Subject: [PATCH 042/894] configure: add hls demuxer link dependencies Fixes building with --disable-everything --enable-demuxer=hls Signed-off-by: Limin Wang --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 92610c7edc..0fe39375ad 100755 --- a/configure +++ b/configure @@ -3363,6 +3363,7 @@ flac_demuxer_select="flac_parser" flv_muxer_select="aac_adtstoasc_bsf" gxf_muxer_select="pcm_rechunk_bsf" hds_muxer_select="flv_muxer" +hls_demuxer_select="adts_header ac3_parser" hls_muxer_select="mpegts_muxer" hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" From f8790ad002886a210d6cd33b96c3502b64f317e8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 11 Oct 2021 17:31:56 +0200 Subject: [PATCH 043/894] avcodec/binkaudio: Remove AV_CODEC_CAP_DELAY This decoder may output multiple AVFrames for every AVPacket passed to it, but after it has returned AVERROR(EAGAIN), it is completely drained and there is no reason to flush it at the end with a NULL packet. Furthermore, there is also no delay in the common sense of the word. Signed-off-by: Andreas Rheinhardt --- libavcodec/binkaudio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index af8cb2809e..5915ba6ffb 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -346,7 +346,7 @@ const AVCodec ff_binkaudio_rdft_decoder = { .init = decode_init, .close = decode_end, .receive_frame = binkaudio_receive_frame, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; @@ -359,6 +359,6 @@ const AVCodec ff_binkaudio_dct_decoder = { .init = decode_init, .close = decode_end, .receive_frame = binkaudio_receive_frame, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; From e84c83ef982042b4441b517a8f23d8427f2b5494 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 11 Oct 2021 17:36:41 +0200 Subject: [PATCH 044/894] avcodec/binkaudio: Properly flush the decoder The packets delivered to this decoder are often decoded to more than one frame and if the internal buffer packet is not unreferenced, the decoder will still output frames derived from the old packet (from before the flush). Signed-off-by: Andreas Rheinhardt --- libavcodec/binkaudio.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index 5915ba6ffb..59ecab25c6 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -337,6 +337,14 @@ fail: return ret; } +static void decode_flush(AVCodecContext *avctx) +{ + BinkAudioContext *const s = avctx->priv_data; + + av_packet_unref(s->pkt); + s->first = 1; +} + const AVCodec ff_binkaudio_rdft_decoder = { .name = "binkaudio_rdft", .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)"), @@ -344,6 +352,7 @@ const AVCodec ff_binkaudio_rdft_decoder = { .id = AV_CODEC_ID_BINKAUDIO_RDFT, .priv_data_size = sizeof(BinkAudioContext), .init = decode_init, + .flush = decode_flush, .close = decode_end, .receive_frame = binkaudio_receive_frame, .capabilities = AV_CODEC_CAP_DR1, @@ -357,6 +366,7 @@ const AVCodec ff_binkaudio_dct_decoder = { .id = AV_CODEC_ID_BINKAUDIO_DCT, .priv_data_size = sizeof(BinkAudioContext), .init = decode_init, + .flush = decode_flush, .close = decode_end, .receive_frame = binkaudio_receive_frame, .capabilities = AV_CODEC_CAP_DR1, From 8c2f142bd91362710fcd42be44dedcafc6d535b8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 28 Oct 2021 21:08:56 +0200 Subject: [PATCH 045/894] avfilter/vf_psnr/ssim: fix typos --- libavfilter/vf_psnr.c | 2 +- libavfilter/vf_ssim.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c index 2b980c17b2..f96179db44 100644 --- a/libavfilter/vf_psnr.c +++ b/libavfilter/vf_psnr.c @@ -22,7 +22,7 @@ /** * @file - * Caculate the PSNR between two input videos. + * Calculate the PSNR between two input videos. */ #include "libavutil/avstring.h" diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c index af1d161e21..c6989d618b 100644 --- a/libavfilter/vf_ssim.c +++ b/libavfilter/vf_ssim.c @@ -31,7 +31,7 @@ /* * @file - * Caculate the SSIM between two input videos. + * Calculate the SSIM between two input videos. */ #include "libavutil/avstring.h" From cd1d09e81b53d47380b494acd3432fd4abb3c17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Thu, 28 Oct 2021 00:38:18 +0300 Subject: [PATCH 046/894] avfilter/vf_zscale: deduplicate output color information setting This way a piece of logic is not missed in one location or the other, such as the case with chroma location outside the if. --- libavfilter/vf_zscale.c | 45 ++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 3f7dba489a..439c0c8548 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -554,6 +554,24 @@ fail: return ret; } +static void update_output_color_information(ZScaleContext *s, AVFrame *frame) +{ + if (s->colorspace != -1) + frame->colorspace = (int)s->dst_format.matrix_coefficients; + + if (s->primaries != -1) + frame->color_primaries = (int)s->dst_format.color_primaries; + + if (s->range != -1) + frame->color_range = convert_range_from_zimg(s->dst_format.pixel_range); + + if (s->trc != -1) + frame->color_trc = (int)s->dst_format.transfer_characteristics; + + if (s->chromal != -1) + frame->chroma_location = (int)s->dst_format.chroma_location - 1; +} + static int filter_frame(AVFilterLink *link, AVFrame *in) { ZScaleContext *s = link->dst->priv; @@ -621,20 +639,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) format_init(&s->dst_format, out, odesc, s->colorspace, s->primaries, s->trc, s->range, s->chromal); - if (s->colorspace != -1) - out->colorspace = (int)s->dst_format.matrix_coefficients; - - if (s->primaries != -1) - out->color_primaries = (int)s->dst_format.color_primaries; - - if (s->range != -1) - out->color_range = convert_range_from_zimg(s->dst_format.pixel_range); - - if (s->trc != -1) - out->color_trc = (int)s->dst_format.transfer_characteristics; - - if (s->chromal != -1) - out->chroma_location = (int)s->dst_format.chroma_location - 1; + update_output_color_information(s, out); ret = graph_build(&s->graph, &s->params, &s->src_format, &s->dst_format, &s->tmp, &s->tmp_size); @@ -680,17 +685,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } } - if (s->colorspace != -1) - out->colorspace = (int)s->dst_format.matrix_coefficients; - - if (s->primaries != -1) - out->color_primaries = (int)s->dst_format.color_primaries; - - if (s->range != -1) - out->color_range = convert_range_from_zimg(s->dst_format.pixel_range); - - if (s->trc != -1) - out->color_trc = (int)s->dst_format.transfer_characteristics; + update_output_color_information(s, out); av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, From 27c0dd55609daf440a7744e96ac20c119bbeb80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Thu, 28 Oct 2021 01:10:14 +0300 Subject: [PATCH 047/894] avfilter/vf_zscale: fix mapping of zimg_chroma_location_e to AVChromaLocation The AVChromaLocation values are one higher than zimg's, not one lower as the undefined value is set to zero (as opposed to zimg's -1). --- libavfilter/vf_zscale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 439c0c8548..1288c5efc1 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -569,7 +569,7 @@ static void update_output_color_information(ZScaleContext *s, AVFrame *frame) frame->color_trc = (int)s->dst_format.transfer_characteristics; if (s->chromal != -1) - frame->chroma_location = (int)s->dst_format.chroma_location - 1; + frame->chroma_location = (int)s->dst_format.chroma_location + 1; } static int filter_frame(AVFilterLink *link, AVFrame *in) From 947d0ce0ea1e54e67bd42a566e7fc1b30d3c7e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20V=C3=A4=C3=A4n=C3=A4nen?= Date: Wed, 22 Sep 2021 15:59:32 +0300 Subject: [PATCH 048/894] avcodec/vqavideo: Decode 15-bit VQA3 files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for 15-bit VQA3 videos used in Westwood Studios' games. Signed-off-by: Pekka Väänänen --- libavcodec/vqavideo.c | 268 ++++++++++++++++++++++++++++++++----- libavformat/westwood_vqa.c | 10 ++ 2 files changed, 248 insertions(+), 30 deletions(-) diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 12698dc2e8..5466e25cdf 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -1,6 +1,7 @@ /* * Westwood Studios VQA Video Decoder - * Copyright (C) 2003 The FFmpeg project + * Copyright (c) 2003 Mike Melanson + * Copyright (c) 2021 Pekka Väänänen * * This file is part of FFmpeg. * @@ -61,6 +62,11 @@ * together and the 8-bit pieces together. If most of the vectors are * clustered into one group of 256 vectors, most of the 4-bit index pieces * should be the same. + * + * VQA3 introduces a 15-bit high color codebook, delta coding, replaces + * the above "split byte" scheme with RLE compression, and extends the + * "format80" compression with relative references. In VQA3 the whole + * codebook is always updated as a whole without splitting it into pieces. */ #include @@ -81,7 +87,7 @@ #define MAX_CODEBOOK_VECTORS 0xFF00 #define SOLID_PIXEL_VECTORS 0x100 #define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS) -#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4) +#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4 * sizeof(uint16_t)) #define CBF0_TAG MKBETAG('C', 'B', 'F', '0') #define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z') @@ -90,9 +96,11 @@ #define CPL0_TAG MKBETAG('C', 'P', 'L', '0') #define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z') #define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z') +#define VPTR_TAG MKBETAG('V', 'P', 'T', 'R') +#define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z') typedef struct VqaContext { - + AVFrame *frame; AVCodecContext *avctx; GetByteContext gb; @@ -104,9 +112,9 @@ typedef struct VqaContext { int vector_height; /* height of individual vector */ int vqa_version; /* this should be either 1, 2 or 3 */ - unsigned char *codebook; /* the current codebook */ + unsigned char *codebook; /* the current codebook */ int codebook_size; - unsigned char *next_codebook_buffer; /* accumulator for next codebook */ + unsigned char *next_codebook_buffer; /* accumulator for next codebook */ int next_codebook_buffer_index; unsigned char *decode_buffer; @@ -115,16 +123,15 @@ typedef struct VqaContext { /* number of frames to go before replacing codebook */ int partial_countdown; int partial_count; - } VqaContext; static av_cold int vqa_decode_init(AVCodecContext *avctx) { VqaContext *s = avctx->priv_data; int i, j, codebook_index, ret; + int colors; s->avctx = avctx; - avctx->pix_fmt = AV_PIX_FMT_PAL8; /* make sure the extradata made it */ if (s->avctx->extradata_size != VQA_HEADER_SIZE) { @@ -134,17 +141,12 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx) /* load up the VQA parameters from the header */ s->vqa_version = s->avctx->extradata[0]; - switch (s->vqa_version) { - case 1: - case 2: - break; - case 3: - avpriv_report_missing_feature(avctx, "VQA Version %d", s->vqa_version); - return AVERROR_PATCHWELCOME; - default: + + if (s->vqa_version < 1 || s->vqa_version > 3) { avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version); - return AVERROR_PATCHWELCOME; + return AVERROR_INVALIDDATA; } + s->width = AV_RL16(&s->avctx->extradata[6]); s->height = AV_RL16(&s->avctx->extradata[8]); if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) { @@ -155,6 +157,14 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx) s->vector_height = s->avctx->extradata[11]; s->partial_count = s->partial_countdown = s->avctx->extradata[13]; + colors = (s->avctx->extradata[14] << 8) | s->avctx->extradata[15]; + + if (colors > 0) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else { + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + } + /* the vector dimensions have to meet very stringent requirements */ if ((s->vector_width != 4) || ((s->vector_height != 2) && (s->vector_height != 4))) { @@ -167,6 +177,10 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + /* allocate codebooks */ s->codebook_size = MAX_CODEBOOK_SIZE; s->codebook = av_malloc(s->codebook_size); @@ -225,6 +239,7 @@ static int decode_format80(VqaContext *s, int src_size, int src_pos; unsigned char color; int i; + int relative = 0; if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) { av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n", @@ -232,6 +247,13 @@ static int decode_format80(VqaContext *s, int src_size, return AVERROR_INVALIDDATA; } + /* the "new" scheme makes references relative to destination pointer */ + if (bytestream2_peek_byte(&s->gb) == 0x00) { + relative = 1; + bytestream2_get_byte(&s->gb); + ff_tlog(s->avctx, "found new format stream "); + } + start = bytestream2_tell(&s->gb); while (bytestream2_tell(&s->gb) - start < src_size) { opcode = bytestream2_get_byte(&s->gb); @@ -251,7 +273,9 @@ static int decode_format80(VqaContext *s, int src_size, count = bytestream2_get_le16(&s->gb); src_pos = bytestream2_get_le16(&s->gb); - ff_tlog(s->avctx, "(1) copy %X bytes from absolute pos %X\n", count, src_pos); + if (relative) + src_pos = dest_index - src_pos; + ff_tlog(s->avctx, "(1) copy %X bytes from pos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(src_pos); for (i = 0; i < count; i++) @@ -271,7 +295,9 @@ static int decode_format80(VqaContext *s, int src_size, count = (opcode & 0x3F) + 3; src_pos = bytestream2_get_le16(&s->gb); - ff_tlog(s->avctx, "(3) copy %X bytes from absolute pos %X\n", count, src_pos); + if (relative) + src_pos = dest_index - src_pos; + ff_tlog(s->avctx, "(3) copy %X bytes from pos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(src_pos); for (i = 0; i < count; i++) @@ -313,7 +339,7 @@ static int decode_format80(VqaContext *s, int src_size, return 0; // let's display what we decoded anyway } -static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) +static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame) { unsigned int chunk_type; unsigned int chunk_size; @@ -512,9 +538,8 @@ static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) break; case 3: -/* not implemented yet */ - lines = 0; - break; + av_log(s->avctx, AV_LOG_ERROR, "VQA3 shouldn't have a color palette"); + return AVERROR_INVALIDDATA; } while (lines--) { @@ -596,24 +621,206 @@ static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) return 0; } +static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) +{ + unsigned int chunk_type; + unsigned int chunk_size; + unsigned int index = 0; + int res; + + int cbf0_chunk = -1; + int cbfz_chunk = -1; + int vptr_chunk = -1; + int vprz_chunk = -1; + + const unsigned char *stream; + + while (bytestream2_get_bytes_left(&s->gb) >= 8) { + chunk_type = bytestream2_get_be32u(&s->gb); + index = bytestream2_tell(&s->gb); + chunk_size = bytestream2_get_be32u(&s->gb); + + switch (chunk_type) { + case CBF0_TAG: + cbf0_chunk = index; + break; + case CBFZ_TAG: + cbfz_chunk = index; + break; + case VPTR_TAG: + vptr_chunk = index; + break; + case VPRZ_TAG: + vprz_chunk = index; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n", + av_fourcc2str(av_bswap32(chunk_type)), chunk_type); + break; + } + + bytestream2_skip(&s->gb, chunk_size + (chunk_size & 0x01)); + } + + /* next, look for a full codebook */ + if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) { + /* a chunk should not have both chunk types */ + av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n"); + return AVERROR_INVALIDDATA; + } + + /* decompress the full codebook chunk */ + if (cbfz_chunk != -1) { + bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + if ((res = decode_format80(s, chunk_size, s->codebook, + s->codebook_size, 0)) < 0) + return res; + } + + /* copy a full codebook */ + if (cbf0_chunk != -1) { + bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + /* sanity check the full codebook size */ + if (chunk_size > MAX_CODEBOOK_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n", + chunk_size); + return AVERROR_INVALIDDATA; + } + + bytestream2_get_buffer(&s->gb, s->codebook, chunk_size); + } + + if (vprz_chunk == -1 && vptr_chunk == -1) { + av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n"); + return AVERROR_INVALIDDATA; + } + + /* decode the frame */ + + if (vptr_chunk != -1) { + /* copy uncompressed tile data */ + bytestream2_seek(&s->gb, vptr_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + if (chunk_size > s->decode_buffer_size) { + av_log(s->avctx, AV_LOG_ERROR, "VPTR chunk didn't fit in decode buffer"); + return AVERROR_INVALIDDATA; + } + bytestream2_get_buffer(&s->gb, s->decode_buffer, chunk_size); + } else if (vprz_chunk != -1) { + /* decompress the tile data */ + bytestream2_seek(&s->gb, vprz_chunk, SEEK_SET); + + chunk_size = bytestream2_get_be32(&s->gb); + if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0) + return res; + } else { + av_log(s->avctx, AV_LOG_ERROR, "expected either VPTR or VPRZ chunk\n"); + return AVERROR_INVALIDDATA; + } + + /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */ + + stream = (unsigned char*)s->decode_buffer; + + for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) { + int x_pos = 0; + + while (x_pos < s->width) { + int vector_index = 0; + int count = 0; + uint16_t code = bytestream_get_le16(&stream); + int type; + + type = code >> 13; + code &= 0x1fff; + + if (type == 0) { + x_pos += 4 * code; + continue; + } else if (type < 3) { + vector_index = code & 0xff; + count = ((code & 0x1f00) >> 7) + 1 + type; + } else if (type < 5) { + vector_index = code; + count = 1; + } else if (type < 7) { + vector_index = code; + count = *stream++; + } else { + av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type); + return AVERROR_INVALIDDATA; + } + + if (count < 0 || count > (s->width - x_pos) / s->vector_width) { + av_log(s->avctx, AV_LOG_ERROR, "invalid count: %d\n", count); + return AVERROR_INVALIDDATA; + } + + while (count-- && x_pos < s->width) { + const int bytes_per_vector = 4 * s->vector_height * sizeof(uint16_t); + unsigned char *src = s->codebook + vector_index * bytes_per_vector; + unsigned char *dst = s->frame->data[0] + y_pos * s->frame->linesize[0] + + sizeof(uint16_t) * x_pos; + + if (vector_index >= MAX_VECTORS) + return AVERROR_INVALIDDATA; + + for (int y = 0; y < s->vector_height; y++) { + int size = 4 * sizeof(uint16_t); + memcpy(dst, src, size); + dst += s->frame->linesize[0]; + src += size; + } + + /* we might want to read the next block index from stream */ + if ((type == 2) && count > 0) { + vector_index = bytestream_get_byte(&stream); + } + + x_pos += 4; + } + + if (count > 0) { + av_log(s->avctx, AV_LOG_ERROR, "had %d leftover vectors\n", count); + return AVERROR_BUG; + } + } + } + + return 0; +} + static int vqa_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { VqaContext *s = avctx->priv_data; - AVFrame *frame = data; int res; - if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0) return res; bytestream2_init(&s->gb, avpkt->data, avpkt->size); - if ((res = vqa_decode_chunk(s, frame)) < 0) - return res; - /* make the palette available on the way out */ - memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4); - frame->palette_has_changed = 1; + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + if ((res = vqa_decode_frame_pal8(s, s->frame)) < 0) + return res; + + /* make the palette available on the way out */ + memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4); + s->frame->palette_has_changed = 1; + } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) { + if ((res = vqa_decode_frame_hicolor(s, s->frame)) < 0) + return res; + } else { + av_log(s->avctx, AV_LOG_ERROR, "unsupported pixel format\n"); + return AVERROR_BUG; + } + + if ((res = av_frame_ref(data, s->frame)) < 0) + return res; *got_frame = 1; @@ -625,6 +832,7 @@ static av_cold int vqa_decode_end(AVCodecContext *avctx) { VqaContext *s = avctx->priv_data; + av_frame_free(&s->frame); av_freep(&s->codebook); av_freep(&s->next_codebook_buffer); av_freep(&s->decode_buffer); @@ -633,7 +841,7 @@ static av_cold int vqa_decode_end(AVCodecContext *avctx) } static const AVCodecDefault vqa_defaults[] = { - { "max_pixels", "320*240" }, + { "max_pixels", "640*480" }, { NULL }, }; diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index bc4f53d4e3..9d116060a3 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -48,10 +48,14 @@ #define CINF_TAG MKBETAG('C', 'I', 'N', 'F') #define CINH_TAG MKBETAG('C', 'I', 'N', 'H') #define CIND_TAG MKBETAG('C', 'I', 'N', 'D') +#define LINF_TAG MKBETAG('L', 'I', 'N', 'F') #define PINF_TAG MKBETAG('P', 'I', 'N', 'F') #define PINH_TAG MKBETAG('P', 'I', 'N', 'H') #define PIND_TAG MKBETAG('P', 'I', 'N', 'D') #define CMDS_TAG MKBETAG('C', 'M', 'D', 'S') +#define SN2J_TAG MKBETAG('S', 'N', '2', 'J') +#define VIEW_TAG MKBETAG('V', 'I', 'E', 'W') +#define ZBUF_TAG MKBETAG('Z', 'B', 'U', 'F') #define VQA_HEADER_SIZE 0x2A #define VQA_PREAMBLE_SIZE 8 @@ -143,11 +147,14 @@ static int wsvqa_read_header(AVFormatContext *s) case CINF_TAG: case CINH_TAG: case CIND_TAG: + case LINF_TAG: case PINF_TAG: case PINH_TAG: case PIND_TAG: case FINF_TAG: case CMDS_TAG: + case VIEW_TAG: + case ZBUF_TAG: break; default: @@ -292,6 +299,9 @@ static int wsvqa_read_packet(AVFormatContext *s, } else { switch(chunk_type){ case CMDS_TAG: + case SN2J_TAG: + case VIEW_TAG: + case ZBUF_TAG: break; default: av_log(s, AV_LOG_INFO, "Skipping unknown chunk %s\n", From 783935de18f4b4c0e5dab7d328648af034a7e676 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Wed, 27 Oct 2021 02:00:38 +1000 Subject: [PATCH 049/894] fftools/ffplay: don't disable x11 compositing Prevents desktop stutters caused by the change (specifically on KDE). We're not a game, we don't actually need it disabled. Reviewed-by: Marton Balint Signed-off-by: Zane van Iperen --- fftools/ffplay.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index ccea0e4578..4b2e69e613 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3746,6 +3746,10 @@ int main(int argc, char **argv) flags |= SDL_WINDOW_BORDERLESS; else flags |= SDL_WINDOW_RESIZABLE; + +#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR + SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); +#endif window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); if (window) { From 3925b826df365a2365118600bd7910cbca95286d Mon Sep 17 00:00:00 2001 From: Alex Shumsky Date: Thu, 21 Oct 2021 19:21:31 +0300 Subject: [PATCH 050/894] avformat/demux: preserve AV_PKT_FLAG_CORRUPT in parse_packet If original packet is corrupted, then parsed packet is probably corrupted too. Let the application decide what to do. Signed-off-by: Alex Shumsky --- libavformat/demux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/demux.c b/libavformat/demux.c index 6a4b687bf1..71a1a9bf03 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -1179,7 +1179,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, out_pkt->pts = sti->parser->pts; out_pkt->dts = sti->parser->dts; out_pkt->pos = sti->parser->pos; - out_pkt->flags |= pkt->flags & AV_PKT_FLAG_DISCARD; + out_pkt->flags |= pkt->flags & (AV_PKT_FLAG_DISCARD | AV_PKT_FLAG_CORRUPT); if (sti->need_parsing == AVSTREAM_PARSE_FULL_RAW) out_pkt->pos = sti->parser->frame_offset; From 81380d221c2b1f9a72b08e4193e6f81774c07b2f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:16:31 +0200 Subject: [PATCH 051/894] avfilter/vf_nlmeans: reduce scope of some variables --- libavfilter/vf_nlmeans.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index 74fc3923b3..b8d8bb2ec0 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -101,14 +101,13 @@ static void compute_safe_ssd_integral_image_c(uint32_t *dst, ptrdiff_t dst_lines const uint8_t *s2, ptrdiff_t linesize2, int w, int h) { - int x, y; const uint32_t *dst_top = dst - dst_linesize_32; /* SIMD-friendly assumptions allowed here */ av_assert2(!(w & 0xf) && w >= 16 && h >= 1); - for (y = 0; y < h; y++) { - for (x = 0; x < w; x += 4) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x += 4) { const int d0 = s1[x ] - s2[x ]; const int d1 = s1[x + 1] - s2[x + 1]; const int d2 = s1[x + 2] - s2[x + 2]; @@ -161,14 +160,12 @@ static inline void compute_unsafe_ssd_integral_image(uint32_t *dst, ptrdiff_t ds int offx, int offy, int r, int sw, int sh, int w, int h) { - int x, y; - - for (y = starty; y < starty + h; y++) { + for (int y = starty; y < starty + h; y++) { uint32_t acc = dst[y*dst_linesize_32 + startx - 1] - dst[(y-1)*dst_linesize_32 + startx - 1]; const int s1y = av_clip(y - r, 0, sh - 1); const int s2y = av_clip(y - (r + offy), 0, sh - 1); - for (x = startx; x < startx + w; x++) { + for (int x = startx; x < startx + w; x++) { const int s1x = av_clip(x - r, 0, sw - 1); const int s2x = av_clip(x - (r + offx), 0, sw - 1); const uint8_t v1 = src[s1y*linesize + s1x]; @@ -334,7 +331,6 @@ struct thread_data { static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - int x, y; NLMeansContext *s = ctx->priv; const struct thread_data *td = arg; const ptrdiff_t src_linesize = td->src_linesize; @@ -349,10 +345,10 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const int dist_d = dist_b * s->ii_lz_32; const int dist_e = dist_d + dist_b; - for (y = starty; y < endy; y++) { + for (int y = starty; y < endy; y++) { const uint8_t *src = td->src + y*src_linesize; struct weighted_avg *wa = s->wa + y*s->wa_linesize; - for (x = td->startx; x < td->endx; x++) { + for (int x = td->startx; x < td->endx; x++) { /* * M is a discrete map where every entry contains the sum of all the entries * in the rectangle from the top-left origin of M to its coordinate. In the @@ -404,10 +400,8 @@ static void weight_averages(uint8_t *dst, ptrdiff_t dst_linesize, struct weighted_avg *wa, ptrdiff_t wa_linesize, int w, int h) { - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { // Also weight the centered pixel wa[x].total_weight += 1.f; wa[x].sum += 1.f * src[x]; @@ -423,7 +417,6 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, uint8_t *dst, ptrdiff_t dst_linesize, const uint8_t *src, ptrdiff_t src_linesize) { - int offx, offy; NLMeansContext *s = ctx->priv; /* patches center points cover the whole research window so the patches * themselves overflow the research window */ @@ -433,8 +426,8 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, memset(s->wa, 0, s->wa_linesize * h * sizeof(*s->wa)); - for (offy = -r; offy <= r; offy++) { - for (offx = -r; offx <= r; offx++) { + for (int offy = -r; offy <= r; offy++) { + for (int offx = -r; offx <= r; offx++) { if (offx || offy) { struct thread_data td = { .src = src + offy*src_linesize + offx, @@ -464,7 +457,6 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - int i; AVFilterContext *ctx = inlink->dst; NLMeansContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -476,7 +468,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } av_frame_copy_props(out, in); - for (i = 0; i < s->nb_planes; i++) { + for (int i = 0; i < s->nb_planes; i++) { const int w = i ? s->chroma_w : inlink->w; const int h = i ? s->chroma_h : inlink->h; const int p = i ? s->patch_hsize_uv : s->patch_hsize; @@ -508,7 +500,6 @@ void ff_nlmeans_init(NLMeansDSPContext *dsp) static av_cold int init(AVFilterContext *ctx) { - int i; NLMeansContext *s = ctx->priv; const double h = s->sigma * 10.; @@ -517,7 +508,7 @@ static av_cold int init(AVFilterContext *ctx) s->weight_lut = av_calloc(s->max_meaningful_diff, sizeof(*s->weight_lut)); if (!s->weight_lut) return AVERROR(ENOMEM); - for (i = 0; i < s->max_meaningful_diff; i++) + for (int i = 0; i < s->max_meaningful_diff; i++) s->weight_lut[i] = exp(-i * s->pdiff_scale); CHECK_ODD_FIELD(research_size, "Luma research window"); From 959ec353ce974ff22863927c0a9dd354d0968c85 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:26:35 +0200 Subject: [PATCH 052/894] avfilter/vf_nlmeans: make access to pointer to lut faster --- libavfilter/vf_nlmeans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index b8d8bb2ec0..0962056a6e 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -344,6 +344,7 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const int dist_b = 2*p + 1; const int dist_d = dist_b * s->ii_lz_32; const int dist_e = dist_d + dist_b; + const float *const weight_lut = s->weight_lut; for (int y = starty; y < endy; y++) { const uint8_t *src = td->src + y*src_linesize; @@ -385,7 +386,7 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const uint32_t patch_diff_sq = e - d - b + a; if (patch_diff_sq < s->max_meaningful_diff) { - const float weight = s->weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) + const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) wa[x].total_weight += weight; wa[x].sum += weight * src[x]; } From 64d19411eb7fe53eef7ab953d1e5d6f06b04ab45 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:28:12 +0200 Subject: [PATCH 053/894] avfilter/vf_nlmeans: no need to print filter options at info level --- libavfilter/vf_nlmeans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index 0962056a6e..d5a71291af 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -526,7 +526,7 @@ static av_cold int init(AVFilterContext *ctx) s->patch_hsize = s->patch_size / 2; s->patch_hsize_uv = s->patch_size_uv / 2; - av_log(ctx, AV_LOG_INFO, "Research window: %dx%d / %dx%d, patch size: %dx%d / %dx%d\n", + av_log(ctx, AV_LOG_DEBUG, "Research window: %dx%d / %dx%d, patch size: %dx%d / %dx%d\n", s->research_size, s->research_size, s->research_size_uv, s->research_size_uv, s->patch_size, s->patch_size, s->patch_size_uv, s->patch_size_uv); From 38c86e7a02c286becbe847ff7bc13d19363ce15e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:40:45 +0200 Subject: [PATCH 054/894] avfilter/vf_nlmeans: avoid if () to help paralellization --- libavfilter/vf_nlmeans.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index d5a71291af..af165c861c 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -332,6 +332,7 @@ struct thread_data { static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { NLMeansContext *s = ctx->priv; + const uint32_t max_meaningful_diff = s->max_meaningful_diff; const struct thread_data *td = arg; const ptrdiff_t src_linesize = td->src_linesize; const int process_h = td->endy - td->starty; @@ -383,13 +384,11 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const uint32_t b = ii[x + dist_b]; const uint32_t d = ii[x + dist_d]; const uint32_t e = ii[x + dist_e]; - const uint32_t patch_diff_sq = e - d - b + a; + const uint32_t patch_diff_sq = FFMIN(e - d - b + a, max_meaningful_diff); + const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) - if (patch_diff_sq < s->max_meaningful_diff) { - const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) - wa[x].total_weight += weight; - wa[x].sum += weight * src[x]; - } + wa[x].total_weight += weight; + wa[x].sum += weight * src[x]; } ii += s->ii_lz_32; } @@ -506,7 +505,7 @@ static av_cold int init(AVFilterContext *ctx) s->pdiff_scale = 1. / (h * h); s->max_meaningful_diff = log(255.) / s->pdiff_scale; - s->weight_lut = av_calloc(s->max_meaningful_diff, sizeof(*s->weight_lut)); + s->weight_lut = av_calloc(s->max_meaningful_diff + 1, sizeof(*s->weight_lut)); if (!s->weight_lut) return AVERROR(ENOMEM); for (int i = 0; i < s->max_meaningful_diff; i++) From eaca36d495f802ebaa5729f345016463d3071c27 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 14:53:28 +0200 Subject: [PATCH 055/894] avfilter/vf_nlmeans: refactor line processing in preparation for x86 SIMD assembly --- libavfilter/vf_nlmeans.c | 107 +++++++++++++++++++++++---------------- libavfilter/vf_nlmeans.h | 14 +++++ 2 files changed, 76 insertions(+), 45 deletions(-) diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index af165c861c..93a14bcf19 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -38,11 +38,6 @@ #include "vf_nlmeans.h" #include "video.h" -struct weighted_avg { - float total_weight; - float sum; -}; - typedef struct NLMeansContext { const AVClass *class; int nb_planes; @@ -329,6 +324,58 @@ struct thread_data { int p; }; +static void compute_weights_line_c(const uint32_t *const iia, + const uint32_t *const iib, + const uint32_t *const iid, + const uint32_t *const iie, + const uint8_t *const src, + struct weighted_avg *wa, + const float *const weight_lut, + int max_meaningful_diff, + int startx, int endx) +{ + for (int x = startx; x < endx; x++) { + /* + * M is a discrete map where every entry contains the sum of all the entries + * in the rectangle from the top-left origin of M to its coordinate. In the + * following schema, "i" contains the sum of the whole map: + * + * M = +----------+-----------------+----+ + * | | | | + * | | | | + * | a| b| c| + * +----------+-----------------+----+ + * | | | | + * | | | | + * | | X | | + * | | | | + * | d| e| f| + * +----------+-----------------+----+ + * | | | | + * | g| h| i| + * +----------+-----------------+----+ + * + * The sum of the X box can be calculated with: + * X = e-d-b+a + * + * See https://en.wikipedia.org/wiki/Summed_area_table + * + * The compute*_ssd functions compute the integral image M where every entry + * contains the sum of the squared difference of every corresponding pixels of + * two input planes of the same size as M. + */ + const uint32_t a = iia[x]; + const uint32_t b = iib[x]; + const uint32_t d = iid[x]; + const uint32_t e = iie[x]; + const uint32_t patch_diff_sq = FFMIN(e - d - b + a, max_meaningful_diff); + const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) + + wa[x].total_weight += weight; + wa[x].sum += weight * src[x]; + } +} + static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { NLMeansContext *s = ctx->priv; @@ -346,50 +393,19 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const int dist_d = dist_b * s->ii_lz_32; const int dist_e = dist_d + dist_b; const float *const weight_lut = s->weight_lut; + NLMeansDSPContext *dsp = &s->dsp; for (int y = starty; y < endy; y++) { - const uint8_t *src = td->src + y*src_linesize; + const uint8_t *const src = td->src + y*src_linesize; struct weighted_avg *wa = s->wa + y*s->wa_linesize; - for (int x = td->startx; x < td->endx; x++) { - /* - * M is a discrete map where every entry contains the sum of all the entries - * in the rectangle from the top-left origin of M to its coordinate. In the - * following schema, "i" contains the sum of the whole map: - * - * M = +----------+-----------------+----+ - * | | | | - * | | | | - * | a| b| c| - * +----------+-----------------+----+ - * | | | | - * | | | | - * | | X | | - * | | | | - * | d| e| f| - * +----------+-----------------+----+ - * | | | | - * | g| h| i| - * +----------+-----------------+----+ - * - * The sum of the X box can be calculated with: - * X = e-d-b+a - * - * See https://en.wikipedia.org/wiki/Summed_area_table - * - * The compute*_ssd functions compute the integral image M where every entry - * contains the sum of the squared difference of every corresponding pixels of - * two input planes of the same size as M. - */ - const uint32_t a = ii[x]; - const uint32_t b = ii[x + dist_b]; - const uint32_t d = ii[x + dist_d]; - const uint32_t e = ii[x + dist_e]; - const uint32_t patch_diff_sq = FFMIN(e - d - b + a, max_meaningful_diff); - const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) + const uint32_t *const iia = ii; + const uint32_t *const iib = ii + dist_b; + const uint32_t *const iid = ii + dist_d; + const uint32_t *const iie = ii + dist_e; - wa[x].total_weight += weight; - wa[x].sum += weight * src[x]; - } + dsp->compute_weights_line(iia, iib, iid, iie, src, wa, + weight_lut, max_meaningful_diff, + td->startx, td->endx); ii += s->ii_lz_32; } return 0; @@ -493,6 +509,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) void ff_nlmeans_init(NLMeansDSPContext *dsp) { dsp->compute_safe_ssd_integral_image = compute_safe_ssd_integral_image_c; + dsp->compute_weights_line = compute_weights_line_c; if (ARCH_AARCH64) ff_nlmeans_init_aarch64(dsp); diff --git a/libavfilter/vf_nlmeans.h b/libavfilter/vf_nlmeans.h index 0a9aab2928..d0d0056163 100644 --- a/libavfilter/vf_nlmeans.h +++ b/libavfilter/vf_nlmeans.h @@ -22,11 +22,25 @@ #include #include +struct weighted_avg { + float total_weight; + float sum; +}; + typedef struct NLMeansDSPContext { void (*compute_safe_ssd_integral_image)(uint32_t *dst, ptrdiff_t dst_linesize_32, const uint8_t *s1, ptrdiff_t linesize1, const uint8_t *s2, ptrdiff_t linesize2, int w, int h); + void (*compute_weights_line)(const uint32_t *const iia, + const uint32_t *const iib, + const uint32_t *const iid, + const uint32_t *const iie, + const uint8_t *const src, + struct weighted_avg *wa, + const float *const weight_lut, + int max_meaningful_diff, + int startx, int endx); } NLMeansDSPContext; void ff_nlmeans_init(NLMeansDSPContext *dsp); From 2b6d290fbf1745c3a562247d8314dd9bab1b9c18 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 29 Oct 2021 16:56:35 +0200 Subject: [PATCH 056/894] avfilter/vf_nlmeans: split wa struct This will make x86 SIMD simpler and faster. --- libavfilter/vf_nlmeans.c | 43 +++++++++++++++++++++++----------------- libavfilter/vf_nlmeans.h | 8 ++------ 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index 93a14bcf19..dee1f68101 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -52,8 +52,9 @@ typedef struct NLMeansContext { uint32_t *ii; // integral image starting after the 0-line and 0-column int ii_w, ii_h; // width and height of the integral image ptrdiff_t ii_lz_32; // linesize in 32-bit units of the integral image - struct weighted_avg *wa; // weighted average of every pixel - ptrdiff_t wa_linesize; // linesize for wa in struct size unit + float *total_weight; // total weight for every pixel + float *sum; // weighted sum for every pixel + int linesize; // sum and total_weight linesize float *weight_lut; // lookup table mapping (scaled) patch differences to their associated weights uint32_t max_meaningful_diff; // maximum difference considered (if the patch difference is too high we ignore the pixel) NLMeansDSPContext dsp; @@ -307,9 +308,10 @@ static int config_input(AVFilterLink *inlink) s->ii = s->ii_orig + s->ii_lz_32 + 1; // allocate weighted average for every pixel - s->wa_linesize = inlink->w; - s->wa = av_malloc_array(s->wa_linesize, inlink->h * sizeof(*s->wa)); - if (!s->wa) + s->linesize = inlink->w; + s->total_weight = av_malloc_array(inlink->w, inlink->h * sizeof(*s->total_weight)); + s->sum = av_malloc_array(inlink->w, inlink->h * sizeof(*s->sum)); + if (!s->total_weight || !s->sum) return AVERROR(ENOMEM); return 0; @@ -329,7 +331,8 @@ static void compute_weights_line_c(const uint32_t *const iia, const uint32_t *const iid, const uint32_t *const iie, const uint8_t *const src, - struct weighted_avg *wa, + float *total_weight, + float *sum, const float *const weight_lut, int max_meaningful_diff, int startx, int endx) @@ -371,8 +374,8 @@ static void compute_weights_line_c(const uint32_t *const iia, const uint32_t patch_diff_sq = FFMIN(e - d - b + a, max_meaningful_diff); const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) - wa[x].total_weight += weight; - wa[x].sum += weight * src[x]; + total_weight[x] += weight; + sum[x] += weight * src[x]; } } @@ -397,13 +400,14 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs for (int y = starty; y < endy; y++) { const uint8_t *const src = td->src + y*src_linesize; - struct weighted_avg *wa = s->wa + y*s->wa_linesize; + float *total_weight = s->total_weight + y*s->linesize; + float *sum = s->sum + y*s->linesize; const uint32_t *const iia = ii; const uint32_t *const iib = ii + dist_b; const uint32_t *const iid = ii + dist_d; const uint32_t *const iie = ii + dist_e; - dsp->compute_weights_line(iia, iib, iid, iie, src, wa, + dsp->compute_weights_line(iia, iib, iid, iie, src, total_weight, sum, weight_lut, max_meaningful_diff, td->startx, td->endx); ii += s->ii_lz_32; @@ -413,19 +417,20 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs static void weight_averages(uint8_t *dst, ptrdiff_t dst_linesize, const uint8_t *src, ptrdiff_t src_linesize, - struct weighted_avg *wa, ptrdiff_t wa_linesize, + float *total_weight, float *sum, ptrdiff_t linesize, int w, int h) { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // Also weight the centered pixel - wa[x].total_weight += 1.f; - wa[x].sum += 1.f * src[x]; - dst[x] = av_clip_uint8(wa[x].sum / wa[x].total_weight + 0.5f); + total_weight[x] += 1.f; + sum[x] += 1.f * src[x]; + dst[x] = av_clip_uint8(sum[x] / total_weight[x] + 0.5f); } dst += dst_linesize; src += src_linesize; - wa += wa_linesize; + total_weight += linesize; + sum += linesize; } } @@ -440,7 +445,8 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, /* focus an integral pointer on the centered image (s1) */ const uint32_t *centered_ii = s->ii + e*s->ii_lz_32 + e; - memset(s->wa, 0, s->wa_linesize * h * sizeof(*s->wa)); + memset(s->total_weight, 0, s->linesize * h * sizeof(*s->total_weight)); + memset(s->sum, 0, s->linesize * h * sizeof(*s->sum)); for (int offy = -r; offy <= r; offy++) { for (int offx = -r; offx <= r; offx++) { @@ -466,7 +472,7 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, } weight_averages(dst, dst_linesize, src, src_linesize, - s->wa, s->wa_linesize, w, h); + s->total_weight, s->sum, s->linesize, w, h); return 0; } @@ -556,7 +562,8 @@ static av_cold void uninit(AVFilterContext *ctx) NLMeansContext *s = ctx->priv; av_freep(&s->weight_lut); av_freep(&s->ii_orig); - av_freep(&s->wa); + av_freep(&s->total_weight); + av_freep(&s->sum); } static const AVFilterPad nlmeans_inputs[] = { diff --git a/libavfilter/vf_nlmeans.h b/libavfilter/vf_nlmeans.h index d0d0056163..cd1ee7c0bf 100644 --- a/libavfilter/vf_nlmeans.h +++ b/libavfilter/vf_nlmeans.h @@ -22,11 +22,6 @@ #include #include -struct weighted_avg { - float total_weight; - float sum; -}; - typedef struct NLMeansDSPContext { void (*compute_safe_ssd_integral_image)(uint32_t *dst, ptrdiff_t dst_linesize_32, const uint8_t *s1, ptrdiff_t linesize1, @@ -37,7 +32,8 @@ typedef struct NLMeansDSPContext { const uint32_t *const iid, const uint32_t *const iie, const uint8_t *const src, - struct weighted_avg *wa, + float *total_weight, + float *sum, const float *const weight_lut, int max_meaningful_diff, int startx, int endx); From ba0ba5539af7ffec19a060e6c1073ff106d77c08 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 29 Oct 2021 15:43:14 -0300 Subject: [PATCH 057/894] fate: update ref files after a recent change Missed in 3925b826df365a2365118600bd7910cbca95286d. Signed-off-by: James Almer --- tests/ref/fate/iv8-demux | 2 +- tests/ref/fate/segment-mp4-to-ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ref/fate/iv8-demux b/tests/ref/fate/iv8-demux index 5b4cf0d4b0..1ca76a49c3 100644 --- a/tests/ref/fate/iv8-demux +++ b/tests/ref/fate/iv8-demux @@ -27,5 +27,5 @@ 0, 72000, 72000, 3600, 20891, 0x3d064fd3 0, 75600, 75600, 3600, 20834, 0xcb774dbc 0, 79200, 79200, 3600, 20870, 0xbc536589 -0, 82800, 82800, 3600, 21421, 0xc99a68e4 +0, 82800, 82800, 3600, 21421, 0xc99a68e4, F=0x3 0, 86400, 86400, 3600, 12869, 0x5684e304 diff --git a/tests/ref/fate/segment-mp4-to-ts b/tests/ref/fate/segment-mp4-to-ts index 8b0746fa92..54fcadb846 100644 --- a/tests/ref/fate/segment-mp4-to-ts +++ b/tests/ref/fate/segment-mp4-to-ts @@ -23,7 +23,7 @@ 0, 50400, 54000, 3600, 607, 0xc53c2339, F=0x0, S=1, 1 0, 54000, 72000, 3600, 4755, 0x2f642b58, F=0x0, S=1, 1 0, 57600, 64800, 3600, 1182, 0xbe1a4847, F=0x0, S=1, 1 -0, 61200, 61200, 3600, 809, 0x8d948a4e, F=0x0, S=1, 1 +0, 61200, 61200, 3600, 809, 0x8d948a4e, F=0x2, S=1, 1 0, 64800, 68400, 3600, 656, 0x4fa03c2b, F=0x0, S=1, 1 0, 68400, 86400, 3600, 26555, 0x5629b584, S=1, 1 0, 72000, 79200, 3600, 1141, 0x761b31e8, F=0x0, S=1, 1 @@ -47,7 +47,7 @@ 0, 136800, 140400, 3600, 754, 0xab1c815e, F=0x0, S=1, 1 0, 140400, 158400, 3600, 5328, 0xd2c55ac6, F=0x0, S=1, 1 0, 144000, 151200, 3600, 1271, 0x46006870, F=0x0, S=1, 1 -0, 147600, 147600, 3600, 849, 0x94dc99c7, F=0x0, S=1, 1 +0, 147600, 147600, 3600, 849, 0x94dc99c7, F=0x2, S=1, 1 0, 151200, 154800, 3600, 753, 0xf4236cab, F=0x0, S=1, 1 0, 154800, 172800, 3600, 25825, 0xd5464dee, S=1, 1 0, 158400, 165600, 3600, 1206, 0x8ce84344, F=0x0, S=1, 1 @@ -95,7 +95,7 @@ 0, 309600, 313200, 3600, 829, 0xffd795cd, F=0x0, S=1, 1 0, 313200, 331200, 3600, 5352, 0x59997996, F=0x0, S=1, 1 0, 316800, 324000, 3600, 1501, 0xb3b8f001, F=0x0, S=1, 1 -0, 320400, 320400, 3600, 941, 0x92b0cb18, F=0x0, S=1, 1 +0, 320400, 320400, 3600, 941, 0x92b0cb18, F=0x2, S=1, 1 0, 324000, 327600, 3600, 823, 0x3d548355, F=0x0, S=1, 1 0, 327600, 345600, 3600, 24042, 0x441e94fb, S=1, 1 0, 331200, 338400, 3600, 1582, 0x4f5d1049, F=0x0, S=1, 1 @@ -119,7 +119,7 @@ 0, 396000, 399600, 3600, 199, 0x79b06355, F=0x0, S=1, 1 0, 399600, 417600, 3600, 1862, 0x22a2a06c, F=0x0, S=1, 1 0, 403200, 410400, 3600, 359, 0x11bdae52, F=0x0, S=1, 1 -0, 406800, 406800, 3600, 235, 0xbec26964, F=0x0, S=1, 1 +0, 406800, 406800, 3600, 235, 0xbec26964, F=0x2, S=1, 1 0, 410400, 414000, 3600, 221, 0x8380682c, F=0x0, S=1, 1 0, 414000, 432000, 3600, 22588, 0xf0ecf072, S=1, 1 0, 417600, 424800, 3600, 383, 0x4f3bb571, F=0x0, S=1, 1 From dbfafe11ae7239e242f9f328fd1e6bdc620e1dba Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sun, 25 Jul 2021 18:31:27 -0400 Subject: [PATCH 058/894] configure: add initial RISC-V support OpenBSD only supports riscv64 but this is an attempt at adding some of the initial bits for RISC-V support. Signed-off-by: Michael Niedermayer --- configure | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0fe39375ad..ede8f9777b 100755 --- a/configure +++ b/configure @@ -2026,6 +2026,7 @@ ARCH_LIST=" parisc ppc ppc64 + riscv s390 sh4 sparc @@ -2636,7 +2637,7 @@ for ext in $(filter_out mmx $ARCH_EXT_LIST_X86_SIMD); do done aligned_stack_if_any="aarch64 ppc x86" -fast_64bit_if_any="aarch64 alpha ia64 mips64 parisc64 ppc64 sparc64 x86_64" +fast_64bit_if_any="aarch64 alpha ia64 mips64 parisc64 ppc64 riscv64 sparc64 x86_64" fast_clz_if_any="aarch64 alpha avr32 mips ppc x86" fast_unaligned_if_any="aarch64 ppc x86" simd_align_16_if_any="altivec neon sse" @@ -4945,6 +4946,9 @@ case "$arch" in "Power Macintosh"|ppc*|powerpc*) arch="ppc" ;; + riscv*) + arch="riscv" + ;; s390|s390x) arch="s390" ;; @@ -5338,6 +5342,10 @@ case "$arch" in check_64bit ppc ppc64 enabled shared && enable_weak pic ;; + riscv) + check_64bit riscv32 riscv64 + enabled shared && enable_weak pic + ;; s390) check_64bit s390 s390x enabled shared && enable_weak pic From 8164fe113910f83e0989d5d151c744895a710710 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 28 Sep 2021 09:25:43 +0200 Subject: [PATCH 059/894] avfilter: add huesaturation filter --- Changelog | 1 + doc/filters.texi | 56 ++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_huesaturation.c | 480 +++++++++++++++++++++++++++++++++ 6 files changed, 540 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_huesaturation.c diff --git a/Changelog b/Changelog index d806b96253..765ec82915 100644 --- a/Changelog +++ b/Changelog @@ -29,6 +29,7 @@ version : - limitdiff video filter - xcorrelate video filter - varblur video filter +- huesaturation video filter version 4.4: diff --git a/doc/filters.texi b/doc/filters.texi index ae6cb3aafd..e5e25ef05a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13908,6 +13908,62 @@ If the specified expression is not valid, it is kept at its current value. @end table +@section huesaturation +Apply hue-saturation-intensity adjustments to input video stream. + +This filter operates in RGB colorspace. + +This filter accepts the following options: + +@table @option +@item hue +Set the hue shift in degrees to apply. Default is 0. +Allowed range is from -180 to 180. + +@item saturation +Set the saturation shift. Default is 0. +Allowed range is from -1 to 1. + +@item intensity +Set the intensity shift. Default is 0. +Allowed range is from -1 to 1. + +@item colors +Set which primary and complementary colors are going to be adjusted. +This options is set by providing one or multiple values. +This can select multiple colors at once. By default all colors are selected. +@table @samp +@item r +Adjust reds. +@item y +Adjust yellows. +@item g +Adjust greens. +@item c +Adjust cyans. +@item b +Adjust blues. +@item m +Adjust magentas. +@item a +Adjust all colors. +@end table + +@item strength +Set strength of filtering. Allowed range is from 0 to 100. +Default value is 1. + +@item rw, gw, bw +Set weight for each RGB component. Allowed range is from 0 to 1. +By default is set to 0.333, 0.334, 0.333. +Those options are used in saturation and lightess processing. + +@item lightness +Set preserving lightness, by default is disabled. +Adjusting hues can change lightness from original RGB triplet, +with this option enabled lightness is kept at same value. +@end table + @section hysteresis Grow first stream into second stream by connecting components. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index e24f419834..933d9628ea 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -305,6 +305,7 @@ OBJS-$(CONFIG_HSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_HSVHOLD_FILTER) += vf_hsvkey.o OBJS-$(CONFIG_HSVKEY_FILTER) += vf_hsvkey.o OBJS-$(CONFIG_HUE_FILTER) += vf_hue.o +OBJS-$(CONFIG_HUESATURATION_FILTER) += vf_huesaturation.o OBJS-$(CONFIG_HWDOWNLOAD_FILTER) += vf_hwdownload.o OBJS-$(CONFIG_HWMAP_FILTER) += vf_hwmap.o OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER) += vf_hwupload_cuda.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9c99f816d3..409ab5d3c4 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -290,6 +290,7 @@ extern const AVFilter ff_vf_hstack; extern const AVFilter ff_vf_hsvhold; extern const AVFilter ff_vf_hsvkey; extern const AVFilter ff_vf_hue; +extern const AVFilter ff_vf_huesaturation; extern const AVFilter ff_vf_hwdownload; extern const AVFilter ff_vf_hwmap; extern const AVFilter ff_vf_hwupload; diff --git a/libavfilter/version.h b/libavfilter/version.h index c04bb7da0d..f6bb4fbe69 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 15 +#define LIBAVFILTER_VERSION_MINOR 16 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_huesaturation.c b/libavfilter/vf_huesaturation.c new file mode 100644 index 0000000000..af7ea33b9e --- /dev/null +++ b/libavfilter/vf_huesaturation.c @@ -0,0 +1,480 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +#define R 0 +#define G 1 +#define B 2 + +#define REDS 0 +#define YELLOWS 1 +#define GREENS 2 +#define CYANS 3 +#define BLUES 4 +#define MAGENTAS 5 + +#define RED (1 << REDS) +#define YELLOW (1 << YELLOWS) +#define GREEN (1 << GREENS) +#define CYAN (1 << CYANS) +#define BLUE (1 << BLUES) +#define MAGENTA (1 << MAGENTAS) +#define ALL 0x3F + +typedef struct HueSaturationContext { + const AVClass *class; + + float hue; + float saturation; + float intensity; + float strength; + float rlw, glw, blw; + int lightness; + int colors; + + int depth; + int planewidth[4]; + int planeheight[4]; + + float matrix[4][4]; + int64_t imatrix[4][4]; + + int bpp; + int step; + uint8_t rgba_map[4]; + + int (*do_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} HueSaturationContext; + +#define DENOM 0x10000 + +static inline void get_triplet(int64_t m[4][4], int *r, int *g, int *b) +{ + const int ir = *r, ig = *g, ib = *b; + + *r = (ir * m[0][0] + ig * m[1][0] + ib * m[2][0] /*+ m[3][0]*/) >> 16; + *g = (ir * m[0][1] + ig * m[1][1] + ib * m[2][1] /*+ m[3][1]*/) >> 16; + *b = (ir * m[0][2] + ig * m[1][2] + ib * m[2][2] /*+ m[3][2]*/) >> 16; +} + +#define FAST_DIV255(x) ((((x) + 128) * 257) >> 16) + +static inline int lerpi8(int v0, int v1, int f, int max) +{ + return v0 + FAST_DIV255((v1 - v0) * f); +} + +static inline int lerpi16(int v0, int v1, int f, int max) +{ + return v0 + (v1 - v0) * (int64_t)f / max; +} + +#define HUESATURATION(name, type, clip, xall) \ +static int do_slice_##name##_##xall(AVFilterContext *ctx, \ + void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + HueSaturationContext *s = ctx->priv; \ + AVFrame *frame = arg; \ + const int imax = (1 << name) - 1; \ + const float strength = s->strength; \ + const int colors = s->colors; \ + const int step = s->step; \ + const int width = frame->width; \ + const int process_h = frame->height; \ + const int slice_start = (process_h * jobnr ) / nb_jobs; \ + const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \ + const int linesize = frame->linesize[0] / sizeof(type); \ + type *row = (type *)frame->data[0] + linesize * slice_start; \ + const uint8_t offset_r = s->rgba_map[R]; \ + const uint8_t offset_g = s->rgba_map[G]; \ + const uint8_t offset_b = s->rgba_map[B]; \ + type *dst_r = row + offset_r; \ + type *dst_g = row + offset_g; \ + type *dst_b = row + offset_b; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width * step; x += step) { \ + int ir, ig, ib, ro, go, bo; \ + \ + ir = ro = dst_r[x]; \ + ig = go = dst_g[x]; \ + ib = bo = dst_b[x]; \ + \ + if (xall) { \ + get_triplet(s->imatrix, &ir, &ig, &ib); \ + } else { \ + const int min = FFMIN3(ir, ig, ib); \ + const int max = FFMAX3(ir, ig, ib); \ + const int flags = (ir == max) << REDS \ + | (ir == min) << CYANS \ + | (ig == max) << GREENS \ + | (ig == min) << MAGENTAS \ + | (ib == max) << BLUES \ + | (ib == min) << YELLOWS; \ + if (colors & flags) { \ + int f = 0; \ + \ + if (colors & RED) \ + f = FFMAX(f, ir - FFMAX(ig, ib)); \ + if (colors & YELLOW) \ + f = FFMAX(f, FFMIN(ir, ig) - ib); \ + if (colors & GREEN) \ + f = FFMAX(f, ig - FFMAX(ir, ib)); \ + if (colors & CYAN) \ + f = FFMAX(f, FFMIN(ig, ib) - ir); \ + if (colors & BLUE) \ + f = FFMAX(f, ib - FFMAX(ir, ig)); \ + if (colors & MAGENTA) \ + f = FFMAX(f, FFMIN(ir, ib) - ig); \ + f = FFMIN(f * strength, imax); \ + get_triplet(s->imatrix, &ir, &ig, &ib); \ + ir = lerpi##name(ro, ir, f, imax); \ + ig = lerpi##name(go, ig, f, imax); \ + ib = lerpi##name(bo, ib, f, imax); \ + } \ + } \ + \ + dst_r[x] = clip(ir); \ + dst_g[x] = clip(ig); \ + dst_b[x] = clip(ib); \ + } \ + \ + dst_r += linesize; \ + dst_g += linesize; \ + dst_b += linesize; \ + } \ + \ + return 0; \ +} + +HUESATURATION(8, uint8_t, av_clip_uint8, 0) +HUESATURATION(16, uint16_t, av_clip_uint16, 0) + +HUESATURATION(8, uint8_t, av_clip_uint8, 1) +HUESATURATION(16, uint16_t, av_clip_uint16, 1) + +static void identity_matrix(float matrix[4][4]) +{ + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + matrix[y][x] = y == x; +} + +static void matrix_multiply(float a[4][4], float b[4][4], float c[4][4]) +{ + float temp[4][4]; + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + temp[y][x] = b[y][0] * a[0][x] + + b[y][1] * a[1][x] + + b[y][2] * a[2][x] + + b[y][3] * a[3][x]; + } + } + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) + c[y][x] = temp[y][x]; + } +} + +static void colorscale_matrix(float matrix[4][4], float r, float g, float b) +{ + float temp[4][4]; + + temp[0][0] = r; temp[0][1] = 0.f; temp[0][2] = 0.f; temp[0][3] = 0.f; + temp[1][0] = 0.f; temp[1][1] = g; temp[1][2] = 0.f; temp[1][3] = 0.f; + temp[2][0] = 0.f; temp[2][1] = 0.f; temp[2][2] = b; temp[2][3] = 0.f; + temp[3][0] = 0.f; temp[3][1] = 0.f; temp[3][2] = 0.f; temp[3][3] = 1.f; + + matrix_multiply(temp, matrix, matrix); +} + +static void saturation_matrix(float matrix[4][4], float saturation, + float rlw, float glw, float blw) +{ + float s = 1.f - saturation; + float a = s * rlw + saturation; + float b = s * rlw; + float c = s * rlw; + float d = s * glw; + float e = s * glw + saturation; + float f = s * glw; + float g = s * blw; + float h = s * blw; + float i = s * blw + saturation; + float m[4][4]; + + m[0][0] = a; m[0][1] = b; m[0][2] = c; m[0][3] = 0.f; + m[1][0] = d; m[1][1] = e; m[1][2] = f; m[1][3] = 0.f; + m[2][0] = g; m[2][1] = h; m[2][2] = i; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void matrix2imatrix(float matrix[4][4], int64_t imatrix[4][4]) +{ + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + imatrix[y][x] = lrintf(matrix[y][x] * DENOM); +} + +static void x_rotate_matrix(float matrix[4][4], float rs, float rc) +{ + float m[4][4]; + + m[0][0] = 1.f; m[0][1] = 0.f; m[0][2] = 0.f; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = rc; m[1][2] = rs; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = -rs; m[2][2] = rc; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void y_rotate_matrix(float matrix[4][4], float rs, float rc) +{ + float m[4][4]; + + m[0][0] = rc; m[0][1] = 0.f; m[0][2] = -rs; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = 1.f; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = rs; m[2][1] = 0.f; m[2][2] = rc; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void z_rotate_matrix(float matrix[4][4], float rs, float rc) +{ + float m[4][4]; + + m[0][0] = rc; m[0][1] = rs; m[0][2] = 0.f; m[0][3] = 0.f; + m[1][0] = -rs; m[1][1] = rc; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = 0.f; m[2][2] = 1.f; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void z_shear_matrix(float matrix[4][4], float dx, float dy) +{ + float m[4][4]; + + m[0][0] = 1.f; m[0][1] = 0.f; m[0][2] = dx; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = 1.f; m[1][2] = dy; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = 0.f; m[2][2] = 1.f; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void transform_point(float matrix[4][4], + float x, float y, float z, + float *tx, float *ty, float *tz) +{ + x = y; + *tx = x; + *tx = x * matrix[0][0] + y * matrix[1][0] + z * matrix[2][0] + matrix[3][0]; + *ty = x * matrix[0][1] + y * matrix[1][1] + z * matrix[2][1] + matrix[3][1]; + *tz = x * matrix[0][2] + y * matrix[1][2] + z * matrix[2][2] + matrix[3][2]; +} + +static void hue_rotate_matrix(float matrix[4][4], float rotation, + float rlw, float glw, float blw) +{ + float mag, lx, ly, lz; + float xrs, xrc; + float yrs, yrc; + float zrs, zrc; + float zsx, zsy; + + mag = M_SQRT2; + xrs = 1.f / mag; + xrc = 1.f / mag; + x_rotate_matrix(matrix, xrs, xrc); + + mag = sqrtf(3.f); + yrs = -1.f / mag; + yrc = M_SQRT2 / mag; + y_rotate_matrix(matrix, yrs, yrc); + + transform_point(matrix, rlw, glw, blw, &lx, &ly, &lz); + zsx = lx / lz; + zsy = ly / lz; + z_shear_matrix(matrix, zsx, zsy); + + zrs = sinf(rotation * M_PI / 180.f); + zrc = cosf(rotation * M_PI / 180.f); + z_rotate_matrix(matrix, zrs, zrc); + + z_shear_matrix(matrix, -zsx, -zsy); + + y_rotate_matrix(matrix, -yrs, yrc); + x_rotate_matrix(matrix, -xrs, xrc); +} + +static void shue_rotate_matrix(float m[4][4], float rotation) +{ + float xrs, xrc, yrs, yrc, zrs, zrc, mag; + + mag = M_SQRT2; + xrs = 1.f / mag; + xrc = 1.f / mag; + x_rotate_matrix(m, xrs, xrc); + + mag = sqrtf(3.f); + yrs = -1.f / mag; + yrc = M_SQRT2 / mag; + y_rotate_matrix(m, yrs, yrc); + + zrs = sinf(rotation * M_PI / 180.f); + zrc = cosf(rotation * M_PI / 180.f); + z_rotate_matrix(m, zrs, zrc); + + y_rotate_matrix(m, -yrs, yrc); + x_rotate_matrix(m, -xrs, xrc); +} + +static void init_matrix(HueSaturationContext *s) +{ + float i = 1.f + s->intensity; + float saturation = 1.f + s->saturation; + float hue = s->hue; + + identity_matrix(s->matrix); + colorscale_matrix(s->matrix, i, i, i); + saturation_matrix(s->matrix, saturation, + s->rlw, s->glw, s->blw); + + if (s->lightness) + hue_rotate_matrix(s->matrix, hue, + s->rlw, s->glw, s->blw); + else + shue_rotate_matrix(s->matrix, hue); + + matrix2imatrix(s->matrix, s->imatrix); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + HueSaturationContext *s = ctx->priv; + + init_matrix(s); + + ff_filter_execute(ctx, s->do_slice[(s->strength >= 99.f) && (s->colors == ALL)], frame, NULL, + FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_ABGR, AV_PIX_FMT_ARGB, + AV_PIX_FMT_0BGR, AV_PIX_FMT_0RGB, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_NONE +}; + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + HueSaturationContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->depth = desc->comp[0].depth; + s->bpp = s->depth >> 3; + s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); + ff_fill_rgba_map(s->rgba_map, inlink->format); + + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + + s->do_slice[0] = s->depth <= 8 ? do_slice_8_0 : do_slice_16_0; + s->do_slice[1] = s->depth <= 8 ? do_slice_8_1 : do_slice_16_1; + + return 0; +} + +static const AVFilterPad huesaturation_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .flags = AVFILTERPAD_FLAG_NEEDS_WRITABLE, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad huesaturation_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +#define OFFSET(x) offsetof(HueSaturationContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption huesaturation_options[] = { + { "hue", "set the hue shift", OFFSET(hue), AV_OPT_TYPE_FLOAT, {.dbl=0},-180, 180, VF }, + { "saturation", "set the saturation shift", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "intensity", "set the intensity shift", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "colors", "set colors range", OFFSET(colors), AV_OPT_TYPE_FLAGS, {.i64=ALL}, 0,ALL,VF, "colors" }, + { "r", "set reds", 0, AV_OPT_TYPE_CONST, {.i64=RED}, 0, 0, VF, "colors" }, + { "y", "set yellows", 0, AV_OPT_TYPE_CONST, {.i64=YELLOW}, 0, 0, VF, "colors" }, + { "g", "set greens", 0, AV_OPT_TYPE_CONST, {.i64=GREEN}, 0, 0, VF, "colors" }, + { "c", "set cyans", 0, AV_OPT_TYPE_CONST, {.i64=CYAN}, 0, 0, VF, "colors" }, + { "b", "set blues", 0, AV_OPT_TYPE_CONST, {.i64=BLUE}, 0, 0, VF, "colors" }, + { "m", "set magentas", 0, AV_OPT_TYPE_CONST, {.i64=MAGENTA}, 0, 0, VF, "colors" }, + { "a", "set all colors", 0, AV_OPT_TYPE_CONST, {.i64=ALL}, 0, 0, VF, "colors" }, + { "strength", "set the filtering strength", OFFSET(strength), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0,100,VF }, + { "rw", "set the red weight", OFFSET(rlw), AV_OPT_TYPE_FLOAT, {.dbl=.333}, 0, 1, VF }, + { "gw", "set the green weight", OFFSET(glw), AV_OPT_TYPE_FLOAT, {.dbl=.334}, 0, 1, VF }, + { "bw", "set the blue weight", OFFSET(blw), AV_OPT_TYPE_FLOAT, {.dbl=.333}, 0, 1, VF }, + { "lightness", "set the preserve lightness", OFFSET(lightness), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(huesaturation); + +const AVFilter ff_vf_huesaturation = { + .name = "huesaturation", + .description = NULL_IF_CONFIG_SMALL("Apply hue-saturation-intensity adjustments."), + .priv_size = sizeof(HueSaturationContext), + .priv_class = &huesaturation_class, + FILTER_INPUTS(huesaturation_inputs), + FILTER_OUTPUTS(huesaturation_outputs), + FILTER_PIXFMTS_ARRAY(pixel_fmts), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; From 4f8494fe5a4307e8661e4d66231f488d644a0524 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 29 Oct 2021 23:24:44 +0200 Subject: [PATCH 060/894] doc/filters: fix typo for hsvkey/hsvhold --- doc/filters.texi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index e5e25ef05a..177f0774fc 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13735,15 +13735,15 @@ The filter accepts the following options: @table @option @item hue -Set the hue value which will be used if color difference calculation. +Set the hue value which will be used in color difference calculation. Allowed range is from -360 to 360. Default value is 0. @item sat -Set the saturation value which will be used if color difference calculation. +Set the saturation value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item val -Set the value which will be used if color difference calculation. +Set the value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item similarity @@ -13773,15 +13773,15 @@ The filter accepts the following options: @table @option @item hue -Set the hue value which will be used if color difference calculation. +Set the hue value which will be used in color difference calculation. Allowed range is from -360 to 360. Default value is 0. @item sat -Set the saturation value which will be used if color difference calculation. +Set the saturation value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item val -Set the value which will be used if color difference calculation. +Set the value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item similarity From d92fdc714496d43234733c315894abe0beeb3529 Mon Sep 17 00:00:00 2001 From: Matt Oliver Date: Wed, 20 Oct 2021 07:02:39 +1100 Subject: [PATCH 061/894] libaom: Dont use aom_codec_av1_dx_algo. This fixes linking errors where variables cannot be correctly linked in from an external shared library such as with msvc (requires dllimport which is not used by libaom). Instead just call the function that returns the same variable. Signed-off-by: Matt Oliver --- libavcodec/libaomdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 75ecc08970..d6b822fda2 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -241,7 +241,7 @@ static av_cold int aom_free(AVCodecContext *avctx) static av_cold int av1_init(AVCodecContext *avctx) { - return aom_init(avctx, &aom_codec_av1_dx_algo); + return aom_init(avctx, aom_codec_av1_dx()); } const AVCodec ff_libaom_av1_decoder = { From 28fac45bde9fd38599a9c2896b58573d8e7303ff Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 30 Oct 2021 10:56:26 -0300 Subject: [PATCH 062/894] avcodec/libaomdec: use intermediate arrays for plane pointers and strides Fixes -Wstringop-overflow warnings with libaom >= 2.0.0, where the unused alpha plane was removed from aom_image. Reviewed-by: James Zern Signed-off-by: James Almer --- libavcodec/libaomdec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index d6b822fda2..64a627ed1c 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -224,9 +224,13 @@ static int aom_decode(AVCodecContext *avctx, void *data, int *got_frame, if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8) image_copy_16_to_8(picture, img); - else - av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes, - img->stride, avctx->pix_fmt, img->d_w, img->d_h); + else { + const uint8_t *planes[4] = { img->planes[0], img->planes[1], img->planes[2] }; + const int stride[4] = { img->stride[0], img->stride[1], img->stride[2] }; + + av_image_copy(picture->data, picture->linesize, planes, + stride, avctx->pix_fmt, img->d_w, img->d_h); + } *got_frame = 1; } return avpkt->size; From 1b04836dff9958e8bfdbed2746b8c40b1e119ecc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 31 Oct 2021 00:02:04 +0200 Subject: [PATCH 063/894] avformat/aiffdec: Check sample_rate Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavformat/aiffdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index a826bc998a..1406347426 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -120,6 +120,9 @@ static int get_aiff_header(AVFormatContext *s, int size, sample_rate = val << exp; else sample_rate = (val + (1ULL<<(-exp-1))) >> -exp; + if (sample_rate <= 0) + return AVERROR_INVALIDDATA; + par->sample_rate = sample_rate; if (size < 18) return AVERROR_INVALIDDATA; From 93f7776921ed8c5219732210067016c3457e864d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 31 Oct 2021 00:10:39 +0200 Subject: [PATCH 064/894] avformat/aiffdec: sanity check block_align Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavformat/aiffdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 1406347426..648f231a52 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -368,7 +368,7 @@ got_sound: if (!st->codecpar->block_align && st->codecpar->codec_id == AV_CODEC_ID_QCELP) { av_log(s, AV_LOG_WARNING, "qcelp without wave chunk, assuming full rate\n"); st->codecpar->block_align = 35; - } else if (!st->codecpar->block_align) { + } else if (st->codecpar->block_align <= 0) { av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); return -1; } From 905588df975071c03c00b2e923c311b4de65a8f4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 31 Oct 2021 00:11:23 +0200 Subject: [PATCH 065/894] avformat/aiffdec: Use av_rescale() for bitrate Fixes: integer overflow Fixes: 40313/clusterfuzz-testcase-minimized-ffmpeg_dem_AIFF_fuzzer-4814761406103552 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavformat/aiffdec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 648f231a52..7a995c00a6 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -185,8 +185,10 @@ static int get_aiff_header(AVFormatContext *s, int size, par->block_align = (av_get_bits_per_sample(par->codec_id) * par->channels) >> 3; if (aiff->block_duration) { - par->bit_rate = (int64_t)par->sample_rate * (par->block_align << 3) / - aiff->block_duration; + par->bit_rate = av_rescale(par->sample_rate, par->block_align * 8LL, + aiff->block_duration); + if (par->bit_rate < 0) + par->bit_rate = 0; } /* Chunk is over */ From 2171f97cc88fc5a73409c6785a961f11113f8e9b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 1 Nov 2021 18:37:26 +0100 Subject: [PATCH 066/894] avformat/aiffdec: "-1" -> AVERROR_INVALIDDATA Signed-off-by: Michael Niedermayer --- libavformat/aiffdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 7a995c00a6..7afadeb085 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -310,7 +310,7 @@ static int aiff_read_header(AVFormatContext *s) break; case MKTAG('w', 'a', 'v', 'e'): if ((uint64_t)size > (1<<30)) - return -1; + return AVERROR_INVALIDDATA; if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) return ret; if ( (st->codecpar->codec_id == AV_CODEC_ID_QDMC || st->codecpar->codec_id == AV_CODEC_ID_QDM2) @@ -372,7 +372,7 @@ got_sound: st->codecpar->block_align = 35; } else if (st->codecpar->block_align <= 0) { av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); - return -1; + return AVERROR_INVALIDDATA; } /* Now positioned, get the sound data start and end */ From bf9950446d73e4c380bdc0ea8241bbd0f86d7983 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 3 Nov 2021 11:25:04 +0100 Subject: [PATCH 067/894] avfilter/vf_chromanr: improve filtering results --- doc/filters.texi | 8 ++++---- libavfilter/vf_chromanr.c | 32 ++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 177f0774fc..62a580a245 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8048,7 +8048,7 @@ Set threshold for averaging chrominance values. Sum of absolute difference of Y, U and V pixel components of current pixel and neighbour pixels lower than this threshold will be used in averaging. Luma component is left unchanged and is copied to output. -Default value is 30. Allowed range is from 1 to 5000. +Default value is 30. Allowed range is from 1 to 200. @item sizew Set horizontal radius of rectangle used for averaging. @@ -8072,19 +8072,19 @@ Mostly useful to speed-up filtering. Set Y threshold for averaging chrominance values. Set finer control for max allowed difference between Y components of current pixel and neigbour pixels. -Default value is 5000. Allowed range is from 1 to 5000. +Default value is 200. Allowed range is from 1 to 200. @item threu Set U threshold for averaging chrominance values. Set finer control for max allowed difference between U components of current pixel and neigbour pixels. -Default value is 5000. Allowed range is from 1 to 5000. +Default value is 200. Allowed range is from 1 to 200. @item threv Set V threshold for averaging chrominance values. Set finer control for max allowed difference between V components of current pixel and neigbour pixels. -Default value is 5000. Allowed range is from 1 to 5000. +Default value is 200. Allowed range is from 1 to 200. @item distance Set distance type used in calculations. diff --git a/libavfilter/vf_chromanr.c b/libavfilter/vf_chromanr.c index 9c36e02c00..63ec8ff075 100644 --- a/libavfilter/vf_chromanr.c +++ b/libavfilter/vf_chromanr.c @@ -72,7 +72,8 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -#define SQR(x) ((x)*(x)) +#define MANHATTAN_DISTANCE(x, y, z) ((x) + (y) + (z)) +#define EUCLIDEAN_DISTANCE(x, y, z) (sqrtf((x)*(x) + (y)*(y) + (z)*(z))) #define FILTER_FUNC(distance, name, ctype, type, fun) \ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, \ @@ -136,19 +137,22 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, int sv = cv; \ int cn = 1; \ \ - for (int yy = FFMAX(0, y - sizeh); yy < FFMIN(y + sizeh, h); yy += steph) { \ + for (int yy = FFMAX(0, y - sizeh); yy <= FFMIN(y + sizeh, h - 1); yy += steph) { \ const type *in_yptr = (const type *)(in->data[0] + yy * chroma_h * in_ylinesize); \ const type *in_uptr = (const type *)(in->data[1] + yy * in_ulinesize); \ const type *in_vptr = (const type *)(in->data[2] + yy * in_vlinesize); \ \ - for (int xx = FFMAX(0, x - sizew); xx < FFMIN(x + sizew, w); xx += stepw) { \ + for (int xx = FFMAX(0, x - sizew); xx <= FFMIN(x + sizew, w - 1); xx += stepw) { \ const ctype Y = in_yptr[xx * chroma_w]; \ const ctype U = in_uptr[xx]; \ const ctype V = in_vptr[xx]; \ + const ctype cyY = FFABS(cy - Y); \ + const ctype cuU = FFABS(cu - U); \ + const ctype cvV = FFABS(cv - V); \ \ - if (fun(cu - U) + fun(cv - V) + fun(cy - Y) < thres && \ - fun(cu - U) < thres_u && fun(cv - V) < thres_v && \ - fun(cy - Y) < thres_y && \ + if (fun(cyY, cuU, cvV) < thres && \ + cuU < thres_u && cvV < thres_v && \ + cyY < thres_y && \ xx != x && yy != y) { \ su += U; \ sv += V; \ @@ -168,11 +172,11 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, return 0; \ } -FILTER_FUNC(manhattan, 8, int, uint8_t, FFABS) -FILTER_FUNC(manhattan, 16, int, uint16_t, FFABS) +FILTER_FUNC(manhattan, 8, int, uint8_t, MANHATTAN_DISTANCE) +FILTER_FUNC(manhattan, 16, int, uint16_t, MANHATTAN_DISTANCE) -FILTER_FUNC(euclidean, 8, int, uint8_t, SQR) -FILTER_FUNC(euclidean, 16, int64_t, uint16_t, SQR) +FILTER_FUNC(euclidean, 8, int, uint8_t, EUCLIDEAN_DISTANCE) +FILTER_FUNC(euclidean, 16, int64_t, uint16_t, EUCLIDEAN_DISTANCE) static int filter_frame(AVFilterLink *inlink, AVFrame *in) { @@ -238,14 +242,14 @@ static int config_input(AVFilterLink *inlink) #define VF AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption chromanr_options[] = { - { "thres", "set y+u+v threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=30}, 1, 5000, VF }, + { "thres", "set y+u+v threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=30}, 1, 200, VF }, { "sizew", "set horizontal size", OFFSET(sizew), AV_OPT_TYPE_INT, {.i64=5}, 1, 100, VF }, { "sizeh", "set vertical size", OFFSET(sizeh), AV_OPT_TYPE_INT, {.i64=5}, 1, 100, VF }, { "stepw", "set horizontal step", OFFSET(stepw), AV_OPT_TYPE_INT, {.i64=1}, 1, 50, VF }, { "steph", "set vertical step", OFFSET(steph), AV_OPT_TYPE_INT, {.i64=1}, 1, 50, VF }, - { "threy", "set y threshold", OFFSET(threshold_y), AV_OPT_TYPE_FLOAT, {.dbl=5000},1, 5000, VF }, - { "threu", "set u threshold", OFFSET(threshold_u), AV_OPT_TYPE_FLOAT, {.dbl=5000},1, 5000, VF }, - { "threv", "set v threshold", OFFSET(threshold_v), AV_OPT_TYPE_FLOAT, {.dbl=5000},1, 5000, VF }, + { "threy", "set y threshold", OFFSET(threshold_y), AV_OPT_TYPE_FLOAT, {.dbl=200},1, 200, VF }, + { "threu", "set u threshold", OFFSET(threshold_u), AV_OPT_TYPE_FLOAT, {.dbl=200},1, 200, VF }, + { "threv", "set v threshold", OFFSET(threshold_v), AV_OPT_TYPE_FLOAT, {.dbl=200},1, 200, VF }, { "distance", "set distance type", OFFSET(distance), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "distance" }, { "manhattan", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "distance" }, { "euclidean", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, VF, "distance" }, From 6cab5206b0ad94990c435cb7c5cf3b29675e0231 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sun, 31 Oct 2021 19:34:33 +0800 Subject: [PATCH 068/894] avutil/hwcontext_videotoolbox: fix use of unknown builtin '__builtin_available' OSX version: 10.11.6 Apple LLVM version 8.0.0 (clang-800.0.42.1) Target: x86_64-apple-darwin15.6.0 Signed-off-by: Limin Wang --- configure | 8 +++++ libavutil/hwcontext_videotoolbox.c | 54 +++++++++++++++++------------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/configure b/configure index ede8f9777b..c4fb1b7260 100755 --- a/configure +++ b/configure @@ -2329,6 +2329,10 @@ TYPES_LIST=" kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ kCVImageBufferTransferFunction_ITU_R_2100_HLG kCVImageBufferTransferFunction_Linear + kCVImageBufferYCbCrMatrix_ITU_R_2020 + kCVImageBufferColorPrimaries_ITU_R_2020 + kCVImageBufferTransferFunction_ITU_R_2020 + kCVImageBufferTransferFunction_SMPTE_ST_428_1 socklen_t struct_addrinfo struct_group_source_req @@ -6273,6 +6277,10 @@ enabled videotoolbox && { check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_ITU_R_2100_HLG "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_Linear "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferYCbCrMatrix_ITU_R_2020 "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferColorPrimaries_ITU_R_2020 "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_ITU_R_2020 "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_428_1 "-framework CoreVideo" } check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index 58095a1fc9..25f4e17715 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -375,10 +375,11 @@ static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, switch (src->colorspace) { case AVCOL_SPC_BT2020_CL: case AVCOL_SPC_BT2020_NCL: - if (__builtin_available(macOS 10.11, *)) - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_2020; - else - colormatrix = CFSTR("ITU_R_2020"); +#if HAVE_KCVIMAGEBUFFERYCBCRMATRIX_ITU_R_2020 + colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_2020; +#else + colormatrix = CFSTR("ITU_R_2020"); +#endif break; case AVCOL_SPC_BT470BG: case AVCOL_SPC_SMPTE170M: @@ -398,10 +399,11 @@ static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, switch (src->color_primaries) { case AVCOL_PRI_BT2020: - if (__builtin_available(macOS 10.11, *)) - colorpri = kCVImageBufferColorPrimaries_ITU_R_2020; - else - colorpri = CFSTR("ITU_R_2020"); +#if HAVE_KCVIMAGEBUFFERCOLORPRIMARIES_ITU_R_2020 + colorpri = kCVImageBufferColorPrimaries_ITU_R_2020; +#else + colorpri = CFSTR("ITU_R_2020"); +#endif break; case AVCOL_PRI_BT709: colorpri = kCVImageBufferColorPrimaries_ITU_R_709_2; @@ -420,17 +422,19 @@ static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, switch (src->color_trc) { case AVCOL_TRC_SMPTE2084: - if (__builtin_available(macOS 10.13, *)) - colortrc = kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; - else - colortrc = CFSTR("SMPTE_ST_2084_PQ"); +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ + colortrc = kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; +#else + colortrc = CFSTR("SMPTE_ST_2084_PQ"); +#endif break; case AVCOL_TRC_BT2020_10: case AVCOL_TRC_BT2020_12: - if (__builtin_available(macOS 10.11, *)) - colortrc = kCVImageBufferTransferFunction_ITU_R_2020; - else - colortrc = CFSTR("ITU_R_2020"); +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2020 + colortrc = kCVImageBufferTransferFunction_ITU_R_2020; +#else + colortrc = CFSTR("ITU_R_2020"); +#endif break; case AVCOL_TRC_BT709: colortrc = kCVImageBufferTransferFunction_ITU_R_709_2; @@ -439,16 +443,18 @@ static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, colortrc = kCVImageBufferTransferFunction_SMPTE_240M_1995; break; case AVCOL_TRC_SMPTE428: - if (__builtin_available(macOS 10.12, *)) - colortrc = kCVImageBufferTransferFunction_SMPTE_ST_428_1; - else - colortrc = CFSTR("SMPTE_ST_428_1"); +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_428_1 + colortrc = kCVImageBufferTransferFunction_SMPTE_ST_428_1; +#else + colortrc = CFSTR("SMPTE_ST_428_1"); +#endif break; case AVCOL_TRC_ARIB_STD_B67: - if (__builtin_available(macOS 10.13, *)) - colortrc = kCVImageBufferTransferFunction_ITU_R_2100_HLG; - else - colortrc = CFSTR("ITU_R_2100_HLG"); +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + colortrc = kCVImageBufferTransferFunction_ITU_R_2100_HLG; +#else + colortrc = CFSTR("ITU_R_2100_HLG"); +#endif break; case AVCOL_TRC_GAMMA22: gamma = 2.2; From 8dc8c01d6c237546be7d50b9c40a1440f43d8619 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 26 Oct 2021 16:52:52 +0800 Subject: [PATCH 069/894] avutil/parseutils: add qhd(Quad HD) or wqhd(Wide Quad HD) for 1440p Signed-off-by: Limin Wang --- libavutil/parseutils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 7f678cd85a..19bbdde611 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -102,6 +102,7 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "wsxga", 1600,1024 }, { "wuxga", 1920,1200 }, { "woxga", 2560,1600 }, + { "wqhd", 2560,1440 }, { "wqsxga", 3200,2048 }, { "wquxga", 3840,2400 }, { "whsxga", 6400,4096 }, @@ -111,6 +112,7 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "hd480", 852, 480 }, { "hd720", 1280, 720 }, { "hd1080", 1920,1080 }, + { "qhd", 2560,1440 }, { "2k", 2048,1080 }, /* Digital Cinema System Specification */ { "2kdci", 2048,1080 }, { "2kflat", 1998,1080 }, From f05559554c41306698aa98618b140f06775e4bcb Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sun, 10 Oct 2021 22:39:48 +0800 Subject: [PATCH 070/894] avformat/dashenc: Fix comparing double with 0 Signed-off-by: Limin Wang --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 06bbf36c95..94e77c7b8c 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -551,7 +551,7 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; - if (prog_date_time == 0) { + if (fabs(prog_date_time) < 1e-7) { if (os->nb_segments == 1) prog_date_time = c->start_time_s; else From 82e3251dd269bdf3c45b991b12dab1ce7561d542 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 29 Oct 2021 15:49:07 +0800 Subject: [PATCH 071/894] avformat/isom_tags: fix 'ipcm' with samplesize equal to 16 Use PCM_S16 so the codec_id will be updated later according to bits_per_coded_sample. --- libavformat/isom_tags.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index d0400b18fc..62e60470a8 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -312,10 +312,10 @@ const AVCodecTag ff_codec_movaudio_tags[] = { { AV_CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, { AV_CODEC_ID_PCM_S16BE, MKTAG('l', 'p', 'c', 'm') }, { AV_CODEC_ID_PCM_S16LE, MKTAG('l', 'p', 'c', 'm') }, + { AV_CODEC_ID_PCM_S16BE, MKTAG('i', 'p', 'c', 'm') }, + { AV_CODEC_ID_PCM_S16LE, MKTAG('i', 'p', 'c', 'm') }, { AV_CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') }, { AV_CODEC_ID_PCM_S24LE, MKTAG('i', 'n', '2', '4') }, - { AV_CODEC_ID_PCM_S24BE, MKTAG('i', 'p', 'c', 'm') }, - { AV_CODEC_ID_PCM_S24LE, MKTAG('i', 'p', 'c', 'm') }, { AV_CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') }, { AV_CODEC_ID_PCM_S32LE, MKTAG('i', 'n', '3', '2') }, { AV_CODEC_ID_PCM_S8, MKTAG('s', 'o', 'w', 't') }, From 08a501946f95f3a998000ee923aa7fcb35ec0d4e Mon Sep 17 00:00:00 2001 From: Roman Arzumanyan Date: Mon, 6 Sep 2021 15:25:51 +0300 Subject: [PATCH 072/894] avfilter/scale_npp: add scale2ref_npp filter Signed-off-by: Timo Rothenpieler --- configure | 1 + doc/filters.texi | 111 ++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_scale_npp.c | 546 ++++++++++++++++++++++++++++++++++--- 6 files changed, 621 insertions(+), 41 deletions(-) diff --git a/configure b/configure index c4fb1b7260..c01aa480c7 100755 --- a/configure +++ b/configure @@ -3095,6 +3095,7 @@ v4l2_m2m_deps="linux_videodev2_h sem_timedwait" hwupload_cuda_filter_deps="ffnvcodec" scale_npp_filter_deps="ffnvcodec libnpp" +scale2ref_npp_filter_deps="ffnvcodec libnpp" scale_cuda_filter_deps="ffnvcodec" scale_cuda_filter_deps_any="cuda_nvcc cuda_llvm" thumbnail_cuda_filter_deps="ffnvcodec" diff --git a/doc/filters.texi b/doc/filters.texi index 62a580a245..b537e421be 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18494,6 +18494,7 @@ scale_cuda=passthrough=0 @end example @end itemize +@anchor{scale_npp} @section scale_npp Use the NVIDIA Performance Primitives (libnpp) to perform scaling and/or pixel @@ -18570,6 +18571,61 @@ This option can be handy if you need to have a video fit within or exceed a defined resolution using @option{force_original_aspect_ratio} but also have encoder restrictions on width or height divisibility. +@item eval +Specify when to evaluate @var{width} and @var{height} expression. It accepts the following values: + +@table @samp +@item init +Only evaluate expressions once during the filter initialization or when a command is processed. + +@item frame +Evaluate expressions for each incoming frame. + +@end table + +@end table + +The values of the @option{w} and @option{h} options are expressions +containing the following constants: + +@table @var +@item in_w +@item in_h +The input width and height + +@item iw +@item ih +These are the same as @var{in_w} and @var{in_h}. + +@item out_w +@item out_h +The output (scaled) width and height + +@item ow +@item oh +These are the same as @var{out_w} and @var{out_h} + +@item a +The same as @var{iw} / @var{ih} + +@item sar +input sample aspect ratio + +@item dar +The input display aspect ratio. Calculated from @code{(iw / ih) * sar}. + +@item n +The (sequential) number of the input frame, starting from 0. +Only available with @code{eval=frame}. + +@item t +The presentation timestamp of the input frame, expressed as a number of +seconds. Only available with @code{eval=frame}. + +@item pos +The position (byte offset) of the frame in the input stream, or NaN if +this information is unavailable and/or meaningless (for example in case of synthetic video). +Only available with @code{eval=frame}. @end table @section scale2ref @@ -18645,6 +18701,61 @@ If the specified expression is not valid, it is kept at its current value. @end table +@section scale2ref_npp + +Use the NVIDIA Performance Primitives (libnpp) to scale (resize) the input +video, based on a reference video. + +See the @ref{scale_npp} filter for available options, scale2ref_npp supports the same +but uses the reference video instead of the main input as basis. scale2ref_npp +also supports the following additional constants for the @option{w} and +@option{h} options: + +@table @var +@item main_w +@item main_h +The main input video's width and height + +@item main_a +The same as @var{main_w} / @var{main_h} + +@item main_sar +The main input video's sample aspect ratio + +@item main_dar, mdar +The main input video's display aspect ratio. Calculated from +@code{(main_w / main_h) * main_sar}. + +@item main_n +The (sequential) number of the main input frame, starting from 0. +Only available with @code{eval=frame}. + +@item main_t +The presentation timestamp of the main input frame, expressed as a number of +seconds. Only available with @code{eval=frame}. + +@item main_pos +The position (byte offset) of the frame in the main input stream, or NaN if +this information is unavailable and/or meaningless (for example in case of synthetic video). +Only available with @code{eval=frame}. +@end table + +@subsection Examples + +@itemize +@item +Scale a subtitle stream (b) to match the main video (a) in size before overlaying +@example +'scale2ref_npp[b][a];[a][b]overlay_cuda' +@end example + +@item +Scale a logo to 1/10th the height of a video, while preserving its display aspect ratio. +@example +[logo-in][video-in]scale2ref_npp=w=oh*mdar:h=ih/10[logo-out][video-out] +@end example +@end itemize + @section scharr Apply scharr operator to input video stream. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 933d9628ea..552bd4e286 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -415,6 +415,7 @@ OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o +OBJS-$(CONFIG_SCALE2REF_NPP_FILTER) += vf_scale_npp.o scale_eval.o OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o OBJS-$(CONFIG_SCHARR_FILTER) += vf_convolution.o OBJS-$(CONFIG_SCROLL_FILTER) += vf_scroll.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 409ab5d3c4..667b6fc246 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -396,6 +396,7 @@ extern const AVFilter ff_vf_scale_qsv; extern const AVFilter ff_vf_scale_vaapi; extern const AVFilter ff_vf_scale_vulkan; extern const AVFilter ff_vf_scale2ref; +extern const AVFilter ff_vf_scale2ref_npp; extern const AVFilter ff_vf_scdet; extern const AVFilter ff_vf_scharr; extern const AVFilter ff_vf_scroll; diff --git a/libavfilter/version.h b/libavfilter/version.h index f6bb4fbe69..3bd3816698 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 8 #define LIBAVFILTER_VERSION_MINOR 16 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c index 8da335154c..6ce82e5302 100644 --- a/libavfilter/vf_scale_npp.c +++ b/libavfilter/vf_scale_npp.c @@ -25,13 +25,13 @@ #include #include -#include "libavutil/avstring.h" -#include "libavutil/common.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_cuda_internal.h" #include "libavutil/cuda_check.h" #include "libavutil/internal.h" #include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/eval.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -44,6 +44,7 @@ static const enum AVPixelFormat supported_formats[] = { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NV12, AV_PIX_FMT_YUV444P, }; @@ -67,12 +68,62 @@ typedef struct NPPScaleStageContext { struct { int width; int height; - } planes_in[3], planes_out[3]; + } planes_in[4], planes_out[4]; AVBufferRef *frames_ctx; AVFrame *frame; } NPPScaleStageContext; +static const char *const var_names[] = { + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "a", + "sar", + "dar", + "n", + "t", + "pos", + "main_w", + "main_h", + "main_a", + "main_sar", + "main_dar", "mdar", + "main_n", + "main_t", + "main_pos", + NULL +}; + +enum var_name { + VAR_IN_W, VAR_IW, + VAR_IN_H, VAR_IH, + VAR_OUT_W, VAR_OW, + VAR_OUT_H, VAR_OH, + VAR_A, + VAR_SAR, + VAR_DAR, + VAR_N, + VAR_T, + VAR_POS, + VAR_S2R_MAIN_W, + VAR_S2R_MAIN_H, + VAR_S2R_MAIN_A, + VAR_S2R_MAIN_SAR, + VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, + VAR_S2R_MAIN_N, + VAR_S2R_MAIN_T, + VAR_S2R_MAIN_POS, + VARS_NB +}; + +enum EvalMode { + EVAL_MODE_INIT, + EVAL_MODE_FRAME, + EVAL_MODE_NB +}; + typedef struct NPPScaleContext { const AVClass *class; @@ -102,35 +153,269 @@ typedef struct NPPScaleContext { int force_divisible_by; int interp_algo; + + char* size_str; + + AVExpr* w_pexpr; + AVExpr* h_pexpr; + + double var_values[VARS_NB]; + + int eval_mode; } NPPScaleContext; -static int nppscale_init(AVFilterContext *ctx) -{ - NPPScaleContext *s = ctx->priv; - int i; +const AVFilter ff_vf_scale2ref_npp; - if (!strcmp(s->format_str, "same")) { - s->format = AV_PIX_FMT_NONE; +static int config_props(AVFilterLink *outlink); + +static int check_exprs(AVFilterContext* ctx) +{ + NPPScaleContext* scale = ctx->priv; + unsigned vars_w[VARS_NB] = {0}, vars_h[VARS_NB] = {0}; + + if (!scale->w_pexpr && !scale->h_pexpr) + return AVERROR(EINVAL); + + if (scale->w_pexpr) + av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); + if (scale->h_pexpr) + av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); + + if (vars_w[VAR_OUT_W] || vars_w[VAR_OW]) { + av_log(ctx, AV_LOG_ERROR, "Width expression cannot be self-referencing: '%s'.\n", scale->w_expr); + return AVERROR(EINVAL); + } + + if (vars_h[VAR_OUT_H] || vars_h[VAR_OH]) { + av_log(ctx, AV_LOG_ERROR, "Height expression cannot be self-referencing: '%s'.\n", scale->h_expr); + return AVERROR(EINVAL); + } + + if ((vars_w[VAR_OUT_H] || vars_w[VAR_OH]) && + (vars_h[VAR_OUT_W] || vars_h[VAR_OW])) { + av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr); + } + + if (ctx->filter != &ff_vf_scale2ref_npp && + (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || + vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || + vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] || + vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] || + vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] || + vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] || + vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || + vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || + vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS])) { + av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref_npp variables are not valid in scale_npp filter.\n"); + return AVERROR(EINVAL); + } + + if (scale->eval_mode == EVAL_MODE_INIT && + (vars_w[VAR_N] || vars_h[VAR_N] || + vars_w[VAR_T] || vars_h[VAR_T] || + vars_w[VAR_POS] || vars_h[VAR_POS] || + vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || + vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || + vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { + av_log(ctx, AV_LOG_ERROR, "Expressions with frame variables 'n', 't', 'pos' are not valid in init eval_mode.\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int nppscale_parse_expr(AVFilterContext* ctx, char* str_expr, + AVExpr** pexpr_ptr, const char* var, + const char* args) +{ + NPPScaleContext* scale = ctx->priv; + int ret, is_inited = 0; + char* old_str_expr = NULL; + AVExpr* old_pexpr = NULL; + + if (str_expr) { + old_str_expr = av_strdup(str_expr); + if (!old_str_expr) + return AVERROR(ENOMEM); + av_opt_set(scale, var, args, 0); + } + + if (*pexpr_ptr) { + old_pexpr = *pexpr_ptr; + *pexpr_ptr = NULL; + is_inited = 1; + } + + ret = av_expr_parse(pexpr_ptr, args, var_names, NULL, NULL, NULL, NULL, 0, + ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Cannot parse expression for %s: '%s'\n", var, + args); + goto revert; + } + + ret = check_exprs(ctx); + if (ret < 0) + goto revert; + + if (is_inited && (ret = config_props(ctx->outputs[0])) < 0) + goto revert; + + av_expr_free(old_pexpr); + old_pexpr = NULL; + av_freep(&old_str_expr); + + return 0; + +revert: + av_expr_free(*pexpr_ptr); + *pexpr_ptr = NULL; + if (old_str_expr) { + av_opt_set(scale, var, old_str_expr, 0); + av_free(old_str_expr); + } + if (old_pexpr) + *pexpr_ptr = old_pexpr; + + return ret; +} + +static av_cold int nppscale_init(AVFilterContext* ctx) +{ + NPPScaleContext* scale = ctx->priv; + int i, ret; + + if (!strcmp(scale->format_str, "same")) { + scale->format = AV_PIX_FMT_NONE; } else { - s->format = av_get_pix_fmt(s->format_str); - if (s->format == AV_PIX_FMT_NONE) { - av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str); + scale->format = av_get_pix_fmt(scale->format_str); + if (scale->format == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", scale->format_str); return AVERROR(EINVAL); } } - for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { - s->stages[i].frame = av_frame_alloc(); - if (!s->stages[i].frame) + if (scale->size_str && (scale->w_expr || scale->h_expr)) { + av_log(ctx, AV_LOG_ERROR, + "Size and width/height exprs cannot be set at the same time.\n"); + return AVERROR(EINVAL); + } + + if (scale->w_expr && !scale->h_expr) + FFSWAP(char*, scale->w_expr, scale->size_str); + + if (scale->size_str) { + char buf[32]; + ret = av_parse_video_size(&scale->w, &scale->h, scale->size_str); + if (0 > ret) { + av_log(ctx, AV_LOG_ERROR, "Invalid size '%s'\n", scale->size_str); + return ret; + } + + snprintf(buf, sizeof(buf) - 1, "%d", scale->w); + ret = av_opt_set(scale, "w", buf, 0); + if (ret < 0) + return ret; + + snprintf(buf, sizeof(buf) - 1, "%d", scale->h); + ret = av_opt_set(scale, "h", buf, 0); + if (ret < 0) + return ret; + } + + if (!scale->w_expr) { + ret = av_opt_set(scale, "w", "iw", 0); + if (ret < 0) + return ret; + } + + if (!scale->h_expr) { + ret = av_opt_set(scale, "h", "ih", 0); + if (ret < 0) + return ret; + } + + ret = nppscale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); + if (ret < 0) + return ret; + + ret = nppscale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); + if (ret < 0) + return ret; + + for (i = 0; i < FF_ARRAY_ELEMS(scale->stages); i++) { + scale->stages[i].frame = av_frame_alloc(); + if (!scale->stages[i].frame) return AVERROR(ENOMEM); } - s->tmp_frame = av_frame_alloc(); - if (!s->tmp_frame) + scale->tmp_frame = av_frame_alloc(); + if (!scale->tmp_frame) return AVERROR(ENOMEM); return 0; } +static int nppscale_eval_dimensions(AVFilterContext* ctx) +{ + NPPScaleContext* scale = ctx->priv; + const char scale2ref = ctx->filter == &ff_vf_scale2ref_npp; + const AVFilterLink* inlink = ctx->inputs[scale2ref ? 1 : 0]; + char* expr; + int eval_w, eval_h; + int ret; + double res; + + scale->var_values[VAR_IN_W] = scale->var_values[VAR_IW] = inlink->w; + scale->var_values[VAR_IN_H] = scale->var_values[VAR_IH] = inlink->h; + scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = NAN; + scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = NAN; + scale->var_values[VAR_A] = (double)inlink->w / inlink->h; + scale->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (double)inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; + scale->var_values[VAR_DAR] = scale->var_values[VAR_A] * scale->var_values[VAR_SAR]; + + if (scale2ref) { + const AVFilterLink* main_link = ctx->inputs[0]; + + scale->var_values[VAR_S2R_MAIN_W] = main_link->w; + scale->var_values[VAR_S2R_MAIN_H] = main_link->h; + scale->var_values[VAR_S2R_MAIN_A] = (double)main_link->w / main_link->h; + scale->var_values[VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? + (double)main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; + scale->var_values[VAR_S2R_MAIN_DAR] = scale->var_values[VAR_S2R_MDAR] = + scale->var_values[VAR_S2R_MAIN_A] * scale->var_values[VAR_S2R_MAIN_SAR]; + } + + res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); + eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int)res == 0 ? inlink->w : (int)res; + + res = av_expr_eval(scale->h_pexpr, scale->var_values, NULL); + if (isnan(res)) { + expr = scale->h_expr; + ret = AVERROR(EINVAL); + goto fail; + } + eval_h = scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = (int)res == 0 ? inlink->h : (int)res; + + res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); + if (isnan(res)) { + expr = scale->w_expr; + ret = AVERROR(EINVAL); + goto fail; + } + eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int)res == 0 ? inlink->w : (int)res; + + scale->w = eval_w; + scale->h = eval_h; + + return 0; + +fail: + av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'.\n", + expr); + return ret; +} + static void nppscale_uninit(AVFilterContext *ctx) { NPPScaleContext *s = ctx->priv; @@ -141,6 +426,10 @@ static void nppscale_uninit(AVFilterContext *ctx) av_buffer_unref(&s->stages[i].frames_ctx); } av_frame_free(&s->tmp_frame); + + av_expr_free(s->w_pexpr); + av_expr_free(s->h_pexpr); + s->w_pexpr = s->h_pexpr = NULL; } static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx) @@ -164,6 +453,13 @@ static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx) stage->planes_out[i].height = stage->planes_out[0].height >> out_sh; } + if (AV_PIX_FMT_YUVA420P == stage->in_fmt) { + stage->planes_in[3].width = stage->planes_in[0].width; + stage->planes_in[3].height = stage->planes_in[0].height; + stage->planes_out[3].width = stage->planes_out[0].width; + stage->planes_out[3].height = stage->planes_out[0].height; + } + out_ref = av_hwframe_ctx_alloc(device_ctx); if (!out_ref) return AVERROR(ENOMEM); @@ -326,31 +622,32 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig return 0; } -static int nppscale_config_props(AVFilterLink *outlink) +static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; - AVFilterLink *inlink = outlink->src->inputs[0]; + AVFilterLink *inlink0 = outlink->src->inputs[0]; + AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref_npp ? + outlink->src->inputs[1] : + outlink->src->inputs[0]; NPPScaleContext *s = ctx->priv; - int w, h; int ret; - if ((ret = ff_scale_eval_dimensions(s, - s->w_expr, s->h_expr, - inlink, outlink, - &w, &h)) < 0) + if ((ret = nppscale_eval_dimensions(ctx)) < 0) goto fail; - ff_scale_adjust_dimensions(inlink, &w, &h, - s->force_original_aspect_ratio, s->force_divisible_by); + ff_scale_adjust_dimensions(inlink, &s->w, &s->h, + s->force_original_aspect_ratio, + s->force_divisible_by); - if (((int64_t)h * inlink->w) > INT_MAX || - ((int64_t)w * inlink->h) > INT_MAX) + if (s->w > INT_MAX || s->h > INT_MAX || + (s->h * inlink->w) > INT_MAX || + (s->w * inlink->h) > INT_MAX) av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); - outlink->w = w; - outlink->h = h; + outlink->w = s->w; + outlink->h = s->h; - ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h); + ret = init_processing_chain(ctx, inlink0->w, inlink0->h, outlink->w, outlink->h); if (ret < 0) return ret; @@ -370,6 +667,22 @@ fail: return ret; } +static int config_props_ref(AVFilterLink *outlink) +{ + AVFilterLink *inlink = outlink->src->inputs[1]; + AVFilterContext *ctx = outlink->src; + + outlink->w = inlink->w; + outlink->h = inlink->h; + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + outlink->time_base = inlink->time_base; + outlink->frame_rate = inlink->frame_rate; + + ctx->outputs[1]->hw_frames_ctx = av_buffer_ref(ctx->inputs[1]->hw_frames_ctx); + + return 0; +} + static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *stage, AVFrame *out, AVFrame *in) { @@ -454,12 +767,71 @@ static int (*const nppscale_process[])(AVFilterContext *ctx, NPPScaleStageContex [STAGE_INTERLEAVE] = nppscale_interleave, }; -static int nppscale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in) +static int nppscale_scale(AVFilterLink *link, AVFrame *out, AVFrame *in) { + AVFilterContext *ctx = link->dst; NPPScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *src = in; + char buf[32]; int i, ret, last_stage = -1; + int frame_changed; + frame_changed = in->width != link->w || + in->height != link->h || + in->format != link->format || + in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || + in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; + + if (s->eval_mode == EVAL_MODE_FRAME || frame_changed) { + unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; + + av_expr_count_vars(s->w_pexpr, vars_w, VARS_NB); + av_expr_count_vars(s->h_pexpr, vars_h, VARS_NB); + + if (s->eval_mode == EVAL_MODE_FRAME && !frame_changed && ctx->filter != &ff_vf_scale2ref_npp && + !(vars_w[VAR_N] || vars_w[VAR_T] || vars_w[VAR_POS]) && + !(vars_h[VAR_N] || vars_h[VAR_T] || vars_h[VAR_POS]) && + s->w && s->h) + goto scale; + + if (s->eval_mode == EVAL_MODE_INIT) { + snprintf(buf, sizeof(buf)-1, "%d", outlink->w); + av_opt_set(s, "w", buf, 0); + snprintf(buf, sizeof(buf)-1, "%d", outlink->h); + av_opt_set(s, "h", buf, 0); + + ret = nppscale_parse_expr(ctx, NULL, &s->w_pexpr, "width", s->w_expr); + if (ret < 0) + return ret; + + ret = nppscale_parse_expr(ctx, NULL, &s->h_pexpr, "height", s->h_expr); + if (ret < 0) + return ret; + } + + if (ctx->filter == &ff_vf_scale2ref_npp) { + s->var_values[VAR_S2R_MAIN_N] = link->frame_count_out; + s->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base); + s->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } else { + s->var_values[VAR_N] = link->frame_count_out; + s->var_values[VAR_T] = TS2T(in->pts, link->time_base); + s->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } + + link->format = in->format; + link->w = in->width; + link->h = in->height; + + link->sample_aspect_ratio.den = in->sample_aspect_ratio.den; + link->sample_aspect_ratio.num = in->sample_aspect_ratio.num; + + if ((ret = config_props(outlink)) < 0) + return ret; + } + +scale: for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { if (!s->stages[i].stage_needed) continue; @@ -516,7 +888,7 @@ static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in) if (ret < 0) goto fail; - ret = nppscale_scale(ctx, out, in); + ret = nppscale_scale(link, out, in); CHECK_CU(device_hwctx->internal->cuda_dl->cuCtxPopCurrent(&dummy)); if (ret < 0) @@ -535,12 +907,54 @@ fail: return ret; } +static int nppscale_filter_frame_ref(AVFilterLink *link, AVFrame *in) +{ + NPPScaleContext *scale = link->dst->priv; + AVFilterLink *outlink = link->dst->outputs[1]; + int frame_changed; + + frame_changed = in->width != link->w || + in->height != link->h || + in->format != link->format || + in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || + in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; + + if (frame_changed) { + link->format = in->format; + link->w = in->width; + link->h = in->height; + link->sample_aspect_ratio.num = in->sample_aspect_ratio.num; + link->sample_aspect_ratio.den = in->sample_aspect_ratio.den; + + config_props_ref(outlink); + } + + if (scale->eval_mode == EVAL_MODE_FRAME) { + scale->var_values[VAR_N] = link->frame_count_out; + scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); + scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } + + return ff_filter_frame(outlink, in); +} + +static int request_frame(AVFilterLink *outlink) +{ + return ff_request_frame(outlink->src->inputs[0]); +} + +static int request_frame_ref(AVFilterLink *outlink) +{ + return ff_request_frame(outlink->src->inputs[1]); +} + #define OFFSET(x) offsetof(NPPScaleContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) static const AVOption options[] = { - { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, - { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, + { "s", "Output video size", OFFSET(size_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = NPPI_INTER_CUBIC }, 0, INT_MAX, FLAGS, "interp_algo" }, { "nn", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_NN }, 0, 0, FLAGS, "interp_algo" }, @@ -551,11 +965,14 @@ static const AVOption options[] = { { "cubic2p_b05c03", "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03 }, 0, 0, FLAGS, "interp_algo" }, { "super", "supersampling", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER }, 0, 0, FLAGS, "interp_algo" }, { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS }, 0, 0, FLAGS, "interp_algo" }, - { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" }, + { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FLAGS, "force_oar" }, { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" }, { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" }, { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" }, - { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, + { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, FLAGS }, + { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, { .i64 = EVAL_MODE_INIT }, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, + { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_INIT }, 0, 0, FLAGS, "eval" }, + { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_FRAME }, 0, 0, FLAGS, "eval" }, { NULL }, }; @@ -564,6 +981,7 @@ static const AVClass nppscale_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, }; static const AVFilterPad nppscale_inputs[] = { @@ -571,15 +989,15 @@ static const AVFilterPad nppscale_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = nppscale_filter_frame, - }, + } }; static const AVFilterPad nppscale_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = nppscale_config_props, - }, + .config_props = config_props, + } }; const AVFilter ff_vf_scale_npp = { @@ -600,3 +1018,51 @@ const AVFilter ff_vf_scale_npp = { .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; + +static const AVFilterPad nppscale2ref_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = nppscale_filter_frame, + }, + { + .name = "ref", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = nppscale_filter_frame_ref, + } +}; + +static const AVFilterPad nppscale2ref_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + .request_frame= request_frame, + }, + { + .name = "ref", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props_ref, + .request_frame= request_frame_ref, + } +}; + +const AVFilter ff_vf_scale2ref_npp = { + .name = "scale2ref_npp", + .description = NULL_IF_CONFIG_SMALL("NVIDIA Performance Primitives video " + "scaling and format conversion to the " + "given reference."), + + .init = nppscale_init, + .uninit = nppscale_uninit, + + .priv_size = sizeof(NPPScaleContext), + .priv_class = &nppscale_class, + + FILTER_INPUTS(nppscale2ref_inputs), + FILTER_OUTPUTS(nppscale2ref_outputs), + + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), + + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From d2379bd6a03bc57eb9cc027a75f21086474422fe Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Wed, 3 Nov 2021 10:55:14 -0700 Subject: [PATCH 073/894] swscale/input: fix planar_rgb16_to_a for gbrap10be and gbrap12be formats Signed-off-by: Michael Niedermayer --- libswscale/input.c | 2 +- tests/ref/fate/filter-pixfmts-scale | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libswscale/input.c b/libswscale/input.c index 477dc3d6b2..336f957c8c 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -911,7 +911,7 @@ static void planar_rgb_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[ } #define rdpx(src) \ - is_be ? AV_RB16(src) : AV_RL16(src) + (is_be ? AV_RB16(src) : AV_RL16(src)) static av_always_inline void planar_rgb16_to_y(uint8_t *_dst, const uint8_t *_src[4], int width, int bpc, int is_be, int32_t *rgb2yuv) { diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index 07c4ff536d..1623e5c939 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -19,9 +19,9 @@ bgra d8316272bc3a360ef9dff3ecc84520a3 bgra64be 4e6a1b9f9c18b881c27d76611d45f737 bgra64le efeee0abcc658ebcff049d5e74d74943 gbrap 4a100f750ac846b34bfeef0d6893c3de -gbrap10be dc6aea3559ea4fcdda1ccc4f23d2f2fb +gbrap10be 50735fbc471a5ac5a6645c85881f3670 gbrap10le 6e1cba57029fdf0f9d46b5e5cd55112b -gbrap12be dbe3a662c016563529032cd4dfb80262 +gbrap12be 58170165829484b3db4a3b9165198987 gbrap12le 24f5ecb32435b73353517e017c165e31 gbrap16be 31968e6872a46e8174fb57f8920ed10d gbrap16le 8c6758f33671b673b6d30969fc05a23d From f6ab103bb5c2dd494620f7a28ae232efe497a4d1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 1 Nov 2021 18:57:56 -0300 Subject: [PATCH 074/894] avcodec/libx264: fix sei payload leaks on error Signed-off-by: James Almer --- libavcodec/libx264.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 21f434d06d..0766b4a950 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -293,6 +293,18 @@ static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame) } } +static void free_picture(AVCodecContext *ctx) +{ + X264Context *x4 = ctx->priv_data; + x264_picture_t *pic = &x4->pic; + + for (int i = 0; i < pic->extra_sei.num_payloads; i++) + av_free(pic->extra_sei.payloads[i].payload); + av_freep(&pic->extra_sei.payloads); + av_freep(&pic->prop.quant_offsets); + pic->extra_sei.num_payloads = 0; +} + static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -396,15 +408,17 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, roi = (const AVRegionOfInterest*)sd->data; roi_size = roi->self_size; if (!roi_size || sd->size % roi_size != 0) { + free_picture(ctx); av_log(ctx, AV_LOG_ERROR, "Invalid AVRegionOfInterest.self_size.\n"); return AVERROR(EINVAL); } nb_rois = sd->size / roi_size; qoffsets = av_calloc(mbx * mby, sizeof(*qoffsets)); - if (!qoffsets) + if (!qoffsets) { + free_picture(ctx); return AVERROR(ENOMEM); - + } // This list must be iterated in reverse because the first // region in the list applies when regions overlap. for (int i = nb_rois - 1; i >= 0; i--) { @@ -420,6 +434,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, if (roi->qoffset.den == 0) { av_free(qoffsets); + free_picture(ctx); av_log(ctx, AV_LOG_ERROR, "AVRegionOfInterest.qoffset.den must not be zero.\n"); return AVERROR(EINVAL); } @@ -452,7 +467,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, continue; tmp = av_fast_realloc(sei->payloads, &sei_data_size, (sei->num_payloads + 1) * sizeof(*sei_payload)); if (!tmp) { - av_freep(&x4->pic.prop.quant_offsets); + free_picture(ctx); return AVERROR(ENOMEM); } sei->payloads = tmp; @@ -460,7 +475,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, sei_payload = &sei->payloads[sei->num_payloads]; sei_payload->payload = av_memdup(side_data->data, side_data->size); if (!sei_payload->payload) { - av_freep(&x4->pic.prop.quant_offsets); + free_picture(ctx); return AVERROR(ENOMEM); } sei_payload->payload_size = side_data->size; From c42d513ede6bc58b2cc7b0e47f90be27700843f8 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Fri, 5 Nov 2021 16:11:59 +0100 Subject: [PATCH 075/894] lavf/mov: Change default to prefer TFDT time and allow for fallback to SIDX or TFDT --- doc/demuxers.texi | 2 +- libavformat/mov.c | 42 +++++++++++++++++++++++------------ tests/ref/seek/extra-mp4 | 48 ++++++++++++++++++++-------------------- 3 files changed, 53 insertions(+), 39 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 1c9575b2e8..cab8a7072c 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -691,7 +691,7 @@ Don't use mfra box to set timestamps @item use_tfdt For fragmented input, set fragment's starting timestamp to @code{baseMediaDecodeTime} from the @code{tfdt} box. -Default is disabled, which will preferentially use the @code{earliest_presentation_time} from the @code{sidx} box. +Default is enabled, which will prefer to use the @code{tfdt} box to set DTS. Disable to use the @code{earliest_presentation_time} from the @code{sidx} box. In either case, the timestamp from the @code{mfra} box will be used if it's available and @code{use_mfra_for} is set to pts or dts. diff --git a/libavformat/mov.c b/libavformat/mov.c index 3fcb1dc908..8a910a3165 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4828,20 +4828,34 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) dts = frag_stream_info->first_tfra_pts; av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64 ", using it for dts\n", pts); - } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE && !c->use_tfdt) { - // FIXME: sidx earliest_presentation_time is *PTS*, s.b. - // pts = frag_stream_info->sidx_pts; - dts = frag_stream_info->sidx_pts - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64 - ", using it for pts\n", pts); - } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) { - dts = frag_stream_info->tfdt_dts - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64 - ", using it for dts\n", dts); } else { - dts = sc->track_end - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 - ", using it for dts\n", dts); + int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE; + int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE; + int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt; + int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx; + + if (fallback_sidx) { + av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n"); + } + if (fallback_tfdt) { + av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n"); + } + + if (has_tfdt && c->use_tfdt || fallback_tfdt) { + dts = frag_stream_info->tfdt_dts - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64 + ", using it for dts\n", dts); + } else if (has_sidx && !c->use_tfdt || fallback_sidx) { + // FIXME: sidx earliest_presentation_time is *PTS*, s.b. + // pts = frag_stream_info->sidx_pts; + dts = frag_stream_info->sidx_pts - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64 + ", using it for pts\n", pts); + } else { + dts = sc->track_end - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 + ", using it for dts\n", dts); + } } } else { dts = sc->track_end - sc->time_offset; @@ -8533,7 +8547,7 @@ static const AVOption mov_options[] = { FLAGS, "use_mfra_for" }, {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0, FLAGS, "use_mfra_for" }, - {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 0}, + {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS}, { "export_all", "Export unrecognized metadata entries", OFFSET(export_all), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS }, diff --git a/tests/ref/seek/extra-mp4 b/tests/ref/seek/extra-mp4 index c17ce4003c..836f7c74ba 100644 --- a/tests/ref/seek/extra-mp4 +++ b/tests/ref/seek/extra-mp4 @@ -23,10 +23,10 @@ ret: 0 st: 0 flags:0 dts: 126.666667 pts: 126.766667 pos:13428716 size: ret: 0 st: 0 flags:0 dts: 126.700000 pts: 126.700000 pos:13431630 size: 781 ret: 0 st: 0 flags:0 dts: 126.733333 pts: 126.733333 pos:13432411 size: 817 ret: 0 st:-1 flags:0 ts: 50.576668 -ret: 0 st: 0 flags:1 dts: 50.600000 pts: 50.633333 pos:5858254 size: 67903 -ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 1307 -ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 -ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 +ret: 0 st: 0 flags:1 dts: 50.633333 pts: 50.666667 pos:5858254 size: 67903 +ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.766667 pos:5926157 size: 1307 +ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927464 size: 150 +ret: 0 st: 0 flags:0 dts: 50.733333 pts: 50.733333 pos:5927614 size: 176 ret: 0 st:-1 flags:1 ts: 153.470835 ret: 0 st: 0 flags:1 dts: 151.966667 pts: 152.000000 pos:15705355 size:146924 ret: 0 st: 0 flags:0 dts: 152.000000 pts: 152.100000 pos:15852279 size: 1355 @@ -43,10 +43,10 @@ ret: 0 st: 0 flags:0 dts: 0.000000 pts: 0.033333 pos: 1470 size: 24 ret: 0 st: 0 flags:0 dts: 0.033333 pts: 0.066667 pos: 1494 size: 6779 ret: 0 st: 0 flags:0 dts: 0.066667 pts: 0.100000 pos: 8273 size: 11041 ret: 0 st:-1 flags:0 ts: 102.153336 -ret: 0 st: 0 flags:1 dts: 104.066667 pts: 104.100000 pos:11116461 size:112929 -ret: 0 st: 0 flags:0 dts: 104.100000 pts: 104.133333 pos:11229390 size: 585 -ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229975 size: 797 -ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11230772 size: 810 +ret: 0 st: 0 flags:1 dts: 104.100000 pts: 104.133333 pos:11116461 size:112929 +ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229390 size: 585 +ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11229975 size: 797 +ret: 0 st: 0 flags:0 dts: 104.200000 pts: 104.233333 pos:11230772 size: 810 ret: 0 st:-1 flags:1 ts: 25.047503 ret: 0 st: 0 flags:1 dts: 20.233333 pts: 20.266667 pos:2223959 size: 51823 ret: 0 st: 0 flags:0 dts: 20.266667 pts: 20.300000 pos:2275782 size: 488 @@ -58,10 +58,10 @@ ret: 0 st: 0 flags:0 dts: 131.266667 pts: 131.366667 pos:13790182 size: ret: 0 st: 0 flags:0 dts: 131.300000 pts: 131.300000 pos:13792531 size: 571 ret: 0 st: 0 flags:0 dts: 131.333333 pts: 131.333333 pos:13793102 size: 1190 ret: 0 st: 0 flags:1 ts: 50.835833 -ret: 0 st: 0 flags:1 dts: 50.600000 pts: 50.633333 pos:5858254 size: 67903 -ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 1307 -ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 -ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 +ret: 0 st: 0 flags:1 dts: 50.633333 pts: 50.666667 pos:5858254 size: 67903 +ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.766667 pos:5926157 size: 1307 +ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927464 size: 150 +ret: 0 st: 0 flags:0 dts: 50.733333 pts: 50.733333 pos:5927614 size: 176 ret: 0 st:-1 flags:0 ts: 153.730004 ret: 0 st: 0 flags:1 dts: 157.033333 pts: 157.066667 pos:16225365 size: 82738 ret: 0 st: 0 flags:0 dts: 157.066667 pts: 157.166667 pos:16308103 size: 2273 @@ -93,10 +93,10 @@ ret: 0 st: 0 flags:0 dts: 127.866667 pts: 127.966667 pos:13581454 size: ret: 0 st: 0 flags:0 dts: 127.900000 pts: 127.900000 pos:13584390 size: 451 ret: 0 st: 0 flags:0 dts: 127.933333 pts: 127.933333 pos:13584841 size: 537 ret: 0 st: 0 flags:0 ts: 51.095011 -ret: 0 st: 0 flags:1 dts: 52.033333 pts: 52.066667 pos:6028050 size:115809 -ret: 0 st: 0 flags:0 dts: 52.066667 pts: 52.166667 pos:6143859 size: 1620 -ret: 0 st: 0 flags:0 dts: 52.100000 pts: 52.100000 pos:6145479 size: 92 -ret: 0 st: 0 flags:0 dts: 52.133333 pts: 52.133333 pos:6145571 size: 533 +ret: 0 st: 0 flags:1 dts: 52.066667 pts: 52.100000 pos:6028050 size:115809 +ret: 0 st: 0 flags:0 dts: 52.100000 pts: 52.200000 pos:6143859 size: 1620 +ret: 0 st: 0 flags:0 dts: 52.133333 pts: 52.133333 pos:6145479 size: 92 +ret: 0 st: 0 flags:0 dts: 52.166667 pts: 52.166667 pos:6145571 size: 533 ret: 0 st: 0 flags:1 ts: 153.989178 ret: 0 st: 0 flags:1 dts: 153.466667 pts: 153.500000 pos:15867700 size: 96169 ret: 0 st: 0 flags:0 dts: 153.500000 pts: 153.533333 pos:15963869 size: 785 @@ -113,10 +113,10 @@ ret: 0 st: 0 flags:0 dts: 0.000000 pts: 0.033333 pos: 1470 size: 24 ret: 0 st: 0 flags:0 dts: 0.033333 pts: 0.066667 pos: 1494 size: 6779 ret: 0 st: 0 flags:0 dts: 0.066667 pts: 0.100000 pos: 8273 size: 11041 ret: 0 st: 0 flags:0 ts: 102.671678 -ret: 0 st: 0 flags:1 dts: 104.066667 pts: 104.100000 pos:11116461 size:112929 -ret: 0 st: 0 flags:0 dts: 104.100000 pts: 104.133333 pos:11229390 size: 585 -ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229975 size: 797 -ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11230772 size: 810 +ret: 0 st: 0 flags:1 dts: 104.100000 pts: 104.133333 pos:11116461 size:112929 +ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229390 size: 585 +ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11229975 size: 797 +ret: 0 st: 0 flags:0 dts: 104.200000 pts: 104.233333 pos:11230772 size: 810 ret: 0 st: 0 flags:1 ts: 25.565844 ret: 0 st: 0 flags:1 dts: 25.300000 pts: 25.333333 pos:2607246 size: 40273 ret: 0 st: 0 flags:0 dts: 25.333333 pts: 25.433333 pos:2647519 size: 2959 @@ -128,7 +128,7 @@ ret: 0 st: 0 flags:0 dts: 131.266667 pts: 131.366667 pos:13790182 size: ret: 0 st: 0 flags:0 dts: 131.300000 pts: 131.300000 pos:13792531 size: 571 ret: 0 st: 0 flags:0 dts: 131.333333 pts: 131.333333 pos:13793102 size: 1190 ret: 0 st:-1 flags:1 ts: 51.354175 -ret: 0 st: 0 flags:1 dts: 50.600000 pts: 50.633333 pos:5858254 size: 67903 -ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 1307 -ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 -ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 +ret: 0 st: 0 flags:1 dts: 50.633333 pts: 50.666667 pos:5858254 size: 67903 +ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.766667 pos:5926157 size: 1307 +ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927464 size: 150 +ret: 0 st: 0 flags:0 dts: 50.733333 pts: 50.733333 pos:5927614 size: 176 From f6b90d5fef0bd2878227ab073f3ddae53c2e2147 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 21 Oct 2021 16:15:30 +0800 Subject: [PATCH 076/894] avformat/dashenc: enabling streaming automatically for ldash There is a little chance that user specified contradicted options like -streaming 0 -ldash 1, however, it's more likely that user didn't know or forgot to enable streaming for ldash. So enabling streaming automatically to make the feature easier to use, similar like enable FF_MOV_FLAG_FRAGMENT/EMPTY_MOOV/DEFAULT_BASE_MOOF and so on for FF_MOV_FLAG_CMAF. --- libavformat/dashenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 94e77c7b8c..f9ec43689d 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1406,8 +1406,8 @@ static int dash_init(AVFormatContext *s) } if (c->ldash && !c->streaming) { - av_log(s, AV_LOG_WARNING, "LDash option will be ignored as streaming is not enabled\n"); - c->ldash = 0; + av_log(s, AV_LOG_WARNING, "Enabling streaming as LDash is enabled\n"); + c->streaming = 1; } if (c->target_latency && !c->streaming) { From a0f9650046842249233b54b1f9b4aaf03dacf0a7 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 21 Oct 2021 16:15:31 +0800 Subject: [PATCH 077/894] avformat/dashenc: enabling streaming and hls_playlist for lhls Try to make the feature easier to use, especially since the user have enabled -strict experimental manually. The user shouldn't be surprised that hls_playlist is enabled for lhls automatically, so change the log level from warning to info for that. --- doc/muxers.texi | 2 +- libavformat/dashenc.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 7338e8d5d3..8febbd58bf 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -365,7 +365,7 @@ Enable Low-latency HLS(LHLS). Adds #EXT-X-PREFETCH tag with current segment's UR Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are trying to standardize a open LHLS spec. The draft spec is available in https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md This option will also try to comply with the above open spec, till Apple's spec officially supports it. -Applicable only when @var{streaming} and @var{hls_playlist} options are enabled. +It enables @var{streaming} and @var{hls_playlist} options automatically. This is an experimental feature. @item ldash @var{ldash} diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index f9ec43689d..5faf06e11d 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1396,13 +1396,13 @@ static int dash_init(AVFormatContext *s) } if (c->lhls && !c->streaming) { - av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n"); - c->lhls = 0; + av_log(s, AV_LOG_WARNING, "Enabling streaming as LHLS is enabled\n"); + c->streaming = 1; } if (c->lhls && !c->hls_playlist) { - av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n"); - c->lhls = 0; + av_log(s, AV_LOG_INFO, "Enabling hls_playlist as LHLS is enabled\n"); + c->hls_playlist = 1; } if (c->ldash && !c->streaming) { From 7370f1f4c98f922a20d9ac3cdc5c74c2885edbe7 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 21 Oct 2021 16:15:32 +0800 Subject: [PATCH 078/894] doc/muxers: note on Apple's version LHLS for lhls option --- doc/muxers.texi | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 8febbd58bf..7eee8c1be6 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -362,12 +362,13 @@ Ignore IO errors during open and write. Useful for long-duration runs with netwo @item lhls @var{lhls} Enable Low-latency HLS(LHLS). Adds #EXT-X-PREFETCH tag with current segment's URI. -Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are -trying to standardize a open LHLS spec. The draft spec is available in https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md -This option will also try to comply with the above open spec, till Apple's spec officially supports it. +hls.js player folks are trying to standardize an open LHLS spec. The draft spec is available in https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md +This option tries to comply with the above open spec. It enables @var{streaming} and @var{hls_playlist} options automatically. This is an experimental feature. +Note: This is not Apple's version LHLS. See @url{https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis} + @item ldash @var{ldash} Enable Low-latency Dash by constraining the presence and values of some elements. From d9a9b4c877b85fea5a5bad74c3d592a756047f79 Mon Sep 17 00:00:00 2001 From: Brad Isbell Date: Sun, 3 Oct 2021 00:16:05 -0500 Subject: [PATCH 079/894] avdevice/dshow: Use WAVEFORMATEX from AM_MEDIA_TYPE for describing device capabilities. (Fixes #9420) Signed-off-by: Brad Isbell Reviewed-by: Roger Pack Signed-off-by: Michael Niedermayer --- libavdevice/dshow.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 8d0a6fcc09..5c1e4941f3 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -422,28 +422,20 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, goto next; } if (!pformat_set) { - av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n", - acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency, - acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency); + av_log( + avctx, + AV_LOG_INFO, + " ch=%2lu, bits=%2lu, rate=%6lu\n", + fx->nChannels, fx->wBitsPerSample, fx->nSamplesPerSec + ); continue; } - if (ctx->sample_rate) { - if (ctx->sample_rate > acaps->MaximumSampleFrequency || - ctx->sample_rate < acaps->MinimumSampleFrequency) - goto next; - fx->nSamplesPerSec = ctx->sample_rate; - } - if (ctx->sample_size) { - if (ctx->sample_size > acaps->MaximumBitsPerSample || - ctx->sample_size < acaps->MinimumBitsPerSample) - goto next; - fx->wBitsPerSample = ctx->sample_size; - } - if (ctx->channels) { - if (ctx->channels > acaps->MaximumChannels || - ctx->channels < acaps->MinimumChannels) - goto next; - fx->nChannels = ctx->channels; + if ( + (ctx->sample_rate && ctx->sample_rate != fx->nSamplesPerSec) || + (ctx->sample_size && ctx->sample_size != fx->wBitsPerSample) || + (ctx->channels && ctx->channels != fx->nChannels ) + ) { + goto next; } } if (IAMStreamConfig_SetFormat(config, type) != S_OK) From 9d4989f2e17c11d4ee9daa489b6e4f5195d80b99 Mon Sep 17 00:00:00 2001 From: Brad Isbell Date: Wed, 3 Nov 2021 20:38:59 -0500 Subject: [PATCH 080/894] avdevice/dshow: Fix missing PCM sample size option when it is used as the lone option for DirectShow audio capture Signed-off-by: Brad Isbell Reviewed-by: Roger Pack Signed-off-by: Michael Niedermayer --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 5c1e4941f3..e313c9a2bf 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -569,7 +569,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, (ctx->requested_width && ctx->requested_height) || ctx->pixel_format != AV_PIX_FMT_NONE || ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) - || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate)); + || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate || ctx->sample_size)); int format_set = 0; int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog; From a085418303a2e736181919429e9b43c06e916f69 Mon Sep 17 00:00:00 2001 From: Maksym Veremeyenko Date: Wed, 3 Nov 2021 12:57:45 +0200 Subject: [PATCH 081/894] avformat/mpegtsenc: fix first_pcr initial update Commit 6f36eb0da71d22aadf8f056f0966bd86656ea57e claim it fixes endless loop on package generation if muxrate specified and copyts used. But actually it does not work properly if -mpegts_copyts 1 is specified: ffmpeg -y -copyts -i loewe.ts -c:v libx264 -x264opts nal-hrd=cbr:force-cfr=1 -b:v 3500k -minrate 3500k -maxrate 3500k -bufsize 1000k -c:a mp2 -f mpegts -mpegts_copyts 1 -muxrate 4500k -vframes 1000 test.ts ffmpeg generate huge file until it reach zero-based pcr value equal to first dts. Attached patch fixes it. Reviewed-by: Limin Wang Signed-off-by: Marton Balint --- libavformat/mpegtsenc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 184bb52f75..fe2e742c15 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1852,12 +1852,12 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (side_data) stream_id = side_data[0]; - if (ts->copyts < 1) { - if (!ts->first_dts_checked && dts != AV_NOPTS_VALUE) { - ts->first_pcr += dts * 300; - ts->first_dts_checked = 1; - } + if (!ts->first_dts_checked && dts != AV_NOPTS_VALUE) { + ts->first_pcr += dts * 300; + ts->first_dts_checked = 1; + } + if (ts->copyts < 1) { if (pts != AV_NOPTS_VALUE) pts += delay; if (dts != AV_NOPTS_VALUE) From 1728127e8c9407d688943c46f8a0524b8870a9b2 Mon Sep 17 00:00:00 2001 From: Alex Shumsky Date: Thu, 21 Oct 2021 17:58:02 +0300 Subject: [PATCH 082/894] avformat/mpegtsenc: do not include adaptation field in teletext TS packets From ETSI EN 300 472 V1.3.1 (2003-05) Specification for conveying ITU-R System B Teletext in DVB bitstreams: 4.1 Transport Stream (TS) packet format The standard TS packet syntax and semantics are followed, noting the following constraint: - adaptation_field_control only the values "01" and "10" are permitted. Some set top boxes (Motorola, Arris, Zyxel) refuse non-conforming packets. Signed-off-by: Alex Shumsky Signed-off-by: Marton Balint --- libavformat/mpegtsenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index fe2e742c15..e3fba54939 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1564,7 +1564,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, q = get_ts_payload_start(buf); ts_st->discontinuity = 0; } - if (key && is_start && pts != AV_NOPTS_VALUE) { + if (key && is_start && pts != AV_NOPTS_VALUE && + !is_dvb_teletext /* adaptation+payload forbidden for teletext (ETSI EN 300 472 V1.3.1 4.1) */) { // set Random Access for key frames if (ts_st->pcr_period) write_pcr = 1; From 9139dc6140e8fb8d84760f3c567332b41858798d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 11:35:03 +0100 Subject: [PATCH 083/894] avformat/matroskadec: Don't unnecessarily reduce aspect ratio Fixes ticket #9497. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavformat/matroskadec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index b2c4927e43..a4bbbe954e 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2806,7 +2806,7 @@ static int matroska_parse_tracks(AVFormatContext *s) &st->sample_aspect_ratio.den, st->codecpar->height * track->video.display_width * display_width_mul, st->codecpar->width * track->video.display_height * display_height_mul, - 255); + INT_MAX); } if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) sti->need_parsing = AVSTREAM_PARSE_HEADERS; From ffdda740fe7983240b31bee3e058e43a859851a4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Sep 2021 22:34:39 +0200 Subject: [PATCH 084/894] avcodec/internal: Allow receive_frame codecs to use decode_simple pkt Decoders implementing the receive_frame API currently mostly use stack packets to temporarily hold the packet they receive from ff_decode_get_packet(). This role directly parallels the role of in_pkt, the spare packet used in decode_simple_internal for the decoders implementing the traditional decoding API. Said packet is unused by the generic code for the decoders implementing the receive_frame API, so allow them to use it to fulfill the function it already fulfills for the traditional API for both APIs. There is only one caveat in this: The packet is automatically unreferenced in avcodec_flush_buffers(). But this is actually positive as it means the decoders don't have to do this themselves (in case the packet is preserved between receive_frame calls). Signed-off-by: Andreas Rheinhardt --- libavcodec/avcodec.c | 8 ++++---- libavcodec/decode.c | 3 +-- libavcodec/internal.h | 14 +++++++++----- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index ff3d73e237..c00a9b2af8 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -181,11 +181,11 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code avci->buffer_frame = av_frame_alloc(); avci->buffer_pkt = av_packet_alloc(); avci->es.in_frame = av_frame_alloc(); - avci->ds.in_pkt = av_packet_alloc(); + avci->in_pkt = av_packet_alloc(); avci->last_pkt_props = av_packet_alloc(); avci->pkt_props = av_fifo_alloc(sizeof(*avci->last_pkt_props)); if (!avci->buffer_frame || !avci->buffer_pkt || - !avci->es.in_frame || !avci->ds.in_pkt || + !avci->es.in_frame || !avci->in_pkt || !avci->last_pkt_props || !avci->pkt_props) { ret = AVERROR(ENOMEM); goto free_and_end; @@ -408,7 +408,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx) av_fifo_reset(avci->pkt_props); av_frame_unref(avci->es.in_frame); - av_packet_unref(avci->ds.in_pkt); + av_packet_unref(avci->in_pkt); if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) ff_thread_flush(avctx); @@ -473,7 +473,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) } av_packet_free(&avci->last_pkt_props); - av_packet_free(&avci->ds.in_pkt); + av_packet_free(&avci->in_pkt); av_frame_free(&avci->es.in_frame); av_buffer_unref(&avci->pool); diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 294c040716..c44724d150 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -296,8 +296,7 @@ static int64_t guess_correct_pts(AVCodecContext *ctx, static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, int64_t *discarded_samples) { AVCodecInternal *avci = avctx->internal; - DecodeSimpleContext *ds = &avci->ds; - AVPacket *pkt = ds->in_pkt; + AVPacket *const pkt = avci->in_pkt; int got_frame, actual_got_frame; int ret; diff --git a/libavcodec/internal.h b/libavcodec/internal.h index b6180f15a5..a62f8dbd4e 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -112,10 +112,6 @@ # define STRIDE_ALIGN 8 #endif -typedef struct DecodeSimpleContext { - AVPacket *in_pkt; -} DecodeSimpleContext; - typedef struct EncodeSimpleContext { AVFrame *in_frame; } EncodeSimpleContext; @@ -137,7 +133,15 @@ typedef struct AVCodecInternal { void *thread_ctx; - DecodeSimpleContext ds; + /** + * This packet is used to hold the packet given to decoders + * implementing the .decode API; it is unused by the generic + * code for decoders implementing the .receive_frame API and + * may be freely used (but not freed) by them with the caveat + * that the packet will be unreferenced generically in + * avcodec_flush_buffers(). + */ + AVPacket *in_pkt; AVBSFContext *bsf; /** From e3533006225d35107c29f984ef4c4bbd9eefeb1c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 11 Oct 2021 10:02:51 +0200 Subject: [PATCH 085/894] avcodec/binkaudio: Use AVCodecInternal.in_pkt for buffer packet Signed-off-by: Andreas Rheinhardt --- libavcodec/binkaudio.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index 59ecab25c6..f808141ba5 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -140,9 +140,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (ret < 0) return ret; - s->pkt = av_packet_alloc(); - if (!s->pkt) - return AVERROR(ENOMEM); + s->pkt = avctx->internal->in_pkt; return 0; } @@ -277,8 +275,6 @@ static av_cold int decode_end(AVCodecContext *avctx) else if (CONFIG_BINKAUDIO_DCT_DECODER) ff_dct_end(&s->trans.dct); - av_packet_free(&s->pkt); - return 0; } @@ -341,7 +337,8 @@ static void decode_flush(AVCodecContext *avctx) { BinkAudioContext *const s = avctx->priv_data; - av_packet_unref(s->pkt); + /* s->pkt coincides with avctx->internal->in_pkt + * and is unreferenced generically when flushing. */ s->first = 1; } From 9b851c4b92b7c55ec9d626b729350a5761aef183 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Sep 2021 23:19:24 +0200 Subject: [PATCH 086/894] avcodec/crystalhd: Use AVCodecInternal.in_pkt instead of stack packet Signed-off-by: Andreas Rheinhardt --- libavcodec/crystalhd.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 0238ab7378..9202a16a77 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -90,6 +90,9 @@ typedef struct OpaqueList { typedef struct { AVClass *av_class; AVCodecContext *avctx; + /* This packet coincides with AVCodecInternal.in_pkt + * and is not owned by us. */ + AVPacket *pkt; HANDLE dev; uint8_t is_70012; @@ -328,6 +331,7 @@ static av_cold int init(AVCodecContext *avctx) /* Initialize the library */ priv = avctx->priv_data; priv->avctx = avctx; + priv->pkt = avctx->internal->in_pkt; priv->draining = 0; subtype = id2subtype(priv, avctx->codec->id); @@ -703,19 +707,19 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) BC_DTS_STATUS decoder_status = { 0, }; CopyRet rec_ret; CHDContext *priv = avctx->priv_data; + AVPacket *const pkt = priv->pkt; HANDLE dev = priv->dev; int got_frame = 0; int ret = 0; - AVPacket pkt = {0}; av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n"); - ret = ff_decode_get_packet(avctx, &pkt); + ret = ff_decode_get_packet(avctx, pkt); if (ret < 0 && ret != AVERROR_EOF) { return ret; } - while (pkt.size > DtsTxFreeSize(dev)) { + while (pkt->size > DtsTxFreeSize(dev)) { /* * Block until there is space in the buffer for the next packet. * We assume that the hardware will make forward progress at this @@ -724,8 +728,8 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) av_log(avctx, AV_LOG_TRACE, "CrystalHD: Waiting for space in input buffer\n"); } - ret = crystalhd_decode_packet(avctx, &pkt); - av_packet_unref(&pkt); + ret = crystalhd_decode_packet(avctx, pkt); + av_packet_unref(pkt); // crystalhd_is_buffer_full() should avoid this. if (ret == AVERROR(EAGAIN)) { ret = AVERROR_EXTERNAL; From ba91b8b6857e367a05b2d6da0cbcea7b1eaf94d5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Sep 2021 23:19:24 +0200 Subject: [PATCH 087/894] avcodec/cuviddec: Use AVCodecInternal.in_pkt instead of stack packet Signed-off-by: Andreas Rheinhardt --- libavcodec/cuviddec.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index e157777c51..f03bbd8c4b 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -53,6 +53,10 @@ typedef struct CuvidContext CUvideodecoder cudecoder; CUvideoparser cuparser; + /* This packet coincides with AVCodecInternal.in_pkt + * and is not owned by us. */ + AVPacket *pkt; + char *cu_gpu; int nb_surfaces; int drop_second_field; @@ -466,12 +470,12 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) } if (!cuvid_is_buffer_full(avctx)) { - AVPacket pkt = {0}; - ret = ff_decode_get_packet(avctx, &pkt); + AVPacket *const pkt = ctx->pkt; + ret = ff_decode_get_packet(avctx, pkt); if (ret < 0 && ret != AVERROR_EOF) return ret; - ret = cuvid_decode_packet(avctx, &pkt); - av_packet_unref(&pkt); + ret = cuvid_decode_packet(avctx, pkt); + av_packet_unref(pkt); // cuvid_is_buffer_full() should avoid this. if (ret == AVERROR(EAGAIN)) ret = AVERROR_EXTERNAL; @@ -797,6 +801,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) if (probe_desc && probe_desc->nb_components) probed_bit_depth = probe_desc->comp[0].depth; + ctx->pkt = avctx->internal->in_pkt; // Accelerated transcoding scenarios with 'ffmpeg' require that the // pix_fmt be set to AV_PIX_FMT_CUDA early. The sw_pix_fmt, and the // pix_fmt for non-accelerated transcoding, do not need to be correct From 776e9f9e2af40252c93e150be712f848d562fccf Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 11 Oct 2021 16:01:02 +0200 Subject: [PATCH 088/894] avcodec/libdav1d: Don't leak side-data-only packets Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/libdav1d.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 2807210e50..2d5fccec71 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -328,6 +328,9 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) return res; } } + } else if (res >= 0) { + av_packet_unref(&pkt); + return AVERROR(EAGAIN); } } From 31d0487ba23a59cdebb1ce64253b3b05000ad0f3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Sep 2021 23:19:24 +0200 Subject: [PATCH 089/894] avcodec/libdav1d: Use AVCodecInternal.in_pkt instead of stack packet Signed-off-by: Andreas Rheinhardt --- libavcodec/libdav1d.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 2d5fccec71..507aaa1a96 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -40,6 +40,9 @@ typedef struct Libdav1dContext { AVClass *class; Dav1dContext *c; + /* This packet coincides with AVCodecInternal.in_pkt + * and is not owned by us. */ + AVPacket *pkt; AVBufferPool *pool; int pool_size; @@ -214,6 +217,8 @@ static av_cold int libdav1d_init(AVCodecContext *c) #endif int res; + dav1d->pkt = c->internal->in_pkt; + av_log(c, AV_LOG_INFO, "libdav1d %s\n", dav1d_version()); dav1d_default_settings(&s); @@ -292,25 +297,26 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) int res; if (!data->sz) { - AVPacket pkt = { 0 }; + AVPacket *const pkt = dav1d->pkt; - res = ff_decode_get_packet(c, &pkt); + res = ff_decode_get_packet(c, pkt); if (res < 0 && res != AVERROR_EOF) return res; - if (pkt.size) { - res = dav1d_data_wrap(data, pkt.data, pkt.size, libdav1d_data_free, pkt.buf); + if (pkt->size) { + res = dav1d_data_wrap(data, pkt->data, pkt->size, + libdav1d_data_free, pkt->buf); if (res < 0) { - av_packet_unref(&pkt); + av_packet_unref(pkt); return res; } - data->m.timestamp = pkt.pts; - data->m.offset = pkt.pos; - data->m.duration = pkt.duration; + data->m.timestamp = pkt->pts; + data->m.offset = pkt->pos; + data->m.duration = pkt->duration; - pkt.buf = NULL; - av_packet_unref(&pkt); + pkt->buf = NULL; + av_packet_unref(pkt); if (c->reordered_opaque != AV_NOPTS_VALUE) { uint8_t *reordered_opaque = av_malloc(sizeof(c->reordered_opaque)); @@ -329,7 +335,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) } } } else if (res >= 0) { - av_packet_unref(&pkt); + av_packet_unref(pkt); return AVERROR(EAGAIN); } } From 7c5ee237bebbaaac6a2734d1919c005ca9684055 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 11 Oct 2021 16:15:24 +0200 Subject: [PATCH 090/894] avcodec/libdav1d: Use av_memdup() where appropriate Signed-off-by: Andreas Rheinhardt --- libavcodec/libdav1d.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 507aaa1a96..bbc81a9dc9 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -319,13 +319,13 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) av_packet_unref(pkt); if (c->reordered_opaque != AV_NOPTS_VALUE) { - uint8_t *reordered_opaque = av_malloc(sizeof(c->reordered_opaque)); + uint8_t *reordered_opaque = av_memdup(&c->reordered_opaque, + sizeof(c->reordered_opaque)); if (!reordered_opaque) { dav1d_data_unref(data); return AVERROR(ENOMEM); } - memcpy(reordered_opaque, &c->reordered_opaque, sizeof(c->reordered_opaque)); res = dav1d_data_wrap_user_data(data, reordered_opaque, libdav1d_user_data_free, reordered_opaque); if (res < 0) { From cd03a180cb66ca199707ad129a4ab44548711c94 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 11 Oct 2021 10:40:24 +0200 Subject: [PATCH 091/894] avcodec/mjpegdec: Use AVCodecInternal.in_pkt for buffer packet Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegdec.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 7f89641660..8b154ce0ab 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -127,9 +127,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->picture_ptr = s->picture; } - s->pkt = av_packet_alloc(); - if (!s->pkt) - return AVERROR(ENOMEM); + s->pkt = avctx->internal->in_pkt; s->avctx = avctx; ff_blockdsp_init(&s->bdsp, avctx); @@ -2960,8 +2958,6 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) } else if (s->picture_ptr) av_frame_unref(s->picture_ptr); - av_packet_free(&s->pkt); - av_frame_free(&s->smv_frame); av_freep(&s->buffer); From 0370c3e3d4dda36a18fe640bd318b937ee98874d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 7 Nov 2021 19:00:50 +0100 Subject: [PATCH 092/894] avfilter/af_adelay: use outlink where applicable --- libavfilter/af_adelay.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c index c42fa2d175..ed8a8ae739 100644 --- a/libavfilter/af_adelay.c +++ b/libavfilter/af_adelay.c @@ -189,14 +189,15 @@ static int config_input(AVFilterLink *inlink) static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; AudioDelayContext *s = ctx->priv; AVFrame *out_frame; int i; if (ctx->is_disabled || !s->delays) - return ff_filter_frame(ctx->outputs[0], frame); + return ff_filter_frame(outlink, frame); - out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples); + out_frame = ff_get_audio_buffer(outlink, frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); @@ -215,9 +216,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } out_frame->pts = s->next_pts; - s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base); + s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); av_frame_free(&frame); - return ff_filter_frame(ctx->outputs[0], out_frame); + return ff_filter_frame(outlink, out_frame); } static int activate(AVFilterContext *ctx) From 45dc668aea0edac34969b5a1ff76cf9ad3a09be1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 7 Nov 2021 20:44:22 +0100 Subject: [PATCH 093/894] avfilter/f_reverse: readjust frame timestamps for areverse --- libavfilter/f_reverse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavfilter/f_reverse.c b/libavfilter/f_reverse.c index 586d95c063..f7a7e716fa 100644 --- a/libavfilter/f_reverse.c +++ b/libavfilter/f_reverse.c @@ -33,6 +33,7 @@ typedef struct ReverseContext { unsigned int pts_size; int64_t *pts; int flush_idx; + int64_t nb_samples; } ReverseContext; static av_cold int init(AVFilterContext *ctx) @@ -249,7 +250,8 @@ static int areverse_request_frame(AVFilterLink *outlink) if (ret == AVERROR_EOF && s->nb_frames > 0) { AVFrame *out = s->frames[s->nb_frames - 1]; - out->pts = s->pts[s->flush_idx++]; + out->pts = s->pts[s->flush_idx++] - s->nb_samples; + s->nb_samples += s->pts[s->flush_idx] - s->pts[s->flush_idx - 1] - out->nb_samples; if (av_sample_fmt_is_planar(out->format)) reverse_samples_planar(out); From dcf83fd59d42b8ee6a601cdf9fc8946a1aa30520 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 Nov 2021 08:58:38 +0100 Subject: [PATCH 094/894] avfilter/vf_estdif: export distance cost as filter option --- doc/filters.texi | 4 ++++ libavfilter/vf_estdif.c | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index b537e421be..5ebfc11237 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11711,6 +11711,10 @@ Allowed range is from 1 to 15. Specify the search radius for best edge matching. Default value is 2. Allowed range is from 0 to 15. +@item dcost +Specify the distance cost for edge matching. Default value is 0.5. +Allowed range is from 0 to 1. + @item interp Specify the interpolation used. Default is 4-point interpolation. It accepts one of the following values: diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index a8ef93826c..4469cb11bf 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -35,6 +35,7 @@ typedef struct ESTDIFContext { int deint; ///< which frames to deinterlace int rslope; ///< best edge slope search radius int redge; ///< best edge match search radius + float dcost; ///< distance cost for edge matching int interp; ///< type of interpolation int linesize[4]; ///< bytes of pixel data per line for each plane int planewidth[4]; ///< width of each plane @@ -42,7 +43,7 @@ typedef struct ESTDIFContext { int field; ///< which field are we on, 0 or 1 int eof; int depth; - int half; + int max; int nb_planes; int nb_threads; int64_t pts; @@ -52,7 +53,7 @@ typedef struct ESTDIFContext { const uint8_t *prev_line, const uint8_t *next_line, const uint8_t *prev2_line, const uint8_t *next2_line, const uint8_t *prev3_line, const uint8_t *next3_line, - int x, int width, int rslope, int redge, unsigned half, + int x, int width, int rslope, int redge, int depth, int *K); unsigned (*mid_8[3])(const uint8_t *const prev, @@ -92,6 +93,7 @@ static const AVOption estdif_options[] = { CONST("interlaced", "only deinterlace frames marked as interlaced", 1, "deint"), { "rslope", "specify the search radius for edge slope tracing", OFFSET(rslope), AV_OPT_TYPE_INT, {.i64=1}, 1, MAX_R, FLAGS, }, { "redge", "specify the search radius for best edge matching", OFFSET(redge), AV_OPT_TYPE_INT, {.i64=2}, 0, MAX_R, FLAGS, }, + { "dcost", "specify the distance cost for edge matching", OFFSET(dcost), AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, FLAGS, }, { "interp", "specify the type of interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, FLAGS, "interp" }, CONST("2p", "two-point interpolation", 0, "interp"), CONST("4p", "four-point interpolation", 1, "interp"), @@ -239,7 +241,7 @@ static unsigned cost_##ss(const type *const prev, \ COST(uint8_t, 8) COST(uint16_t, 16) -#define INTERPOLATE(type, atype, max, ss) \ +#define INTERPOLATE(type, atype, amax, ss) \ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const uint8_t *const pprev_line, \ const uint8_t *const nnext_line, \ @@ -248,7 +250,7 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const uint8_t *const pprev3_line, \ const uint8_t *const nnext3_line, \ int x, int width, int rslope, \ - int redge, unsigned h, int depth, \ + int redge, int depth, \ int *K) \ { \ type *dst = (type *)ddst; \ @@ -259,10 +261,11 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const type *const next2_line = (const type *const)nnext2_line; \ const type *const next3_line = (const type *const)nnext3_line; \ const int interp = s->interp; \ + const int dcost = s->dcost * s->max; \ const int end = width - 1; \ const atype f = redge + 2; \ atype sd[S], sD[S], di = 0; \ - atype dmin = max; \ + atype dmin = amax; \ int k = *K; \ \ for (int i = -rslope; i <= rslope && abs(k) > rslope; i++) { \ @@ -276,7 +279,7 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ \ sD[i + rslope] = sum; \ sD[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, i); \ - sD[i + rslope] += h * abs(i); \ + sD[i + rslope] += dcost * abs(i); \ \ dmin = FFMIN(sD[i + rslope], dmin); \ } \ @@ -292,7 +295,7 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ \ sd[i + rslope] = sum; \ sd[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, k + i); \ - sd[i + rslope] += h * abs(k + i); \ + sd[i + rslope] += dcost * abs(k + i); \ \ dmin = FFMIN(sd[i + rslope], dmin); \ } \ @@ -332,7 +335,6 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg, AVFrame *in = td->in; const int rslope = s->rslope; const int redge = s->redge; - const int half = s->half; const int depth = s->depth; const int interlaced = in->interlaced_frame; const int tff = (s->field == (s->parity == -1 ? interlaced ? in->top_field_first : 1 : @@ -411,7 +413,7 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg, prev_line, next_line, prev2_line, next2_line, prev3_line, next3_line, - x, width, rslope, redge, half, depth, &k); + x, width, rslope, redge, depth, &k); } out_line += 2 * dst_linesize; @@ -475,7 +477,7 @@ static int config_input(AVFilterLink *inlink) s->mid_16[0] = mid2_16; s->mid_16[1] = mid4_16; s->mid_16[2] = mid6_16; - s->half = 1 << (s->depth - 1); + s->max = (1 << (s->depth)) - 1; return 0; } From a13646639fcddb1de3bf08c25a243218cec39a0b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 Nov 2021 09:32:20 +0100 Subject: [PATCH 095/894] avfilter/vf_estdif: do some clip calculations only once in loop --- libavfilter/vf_estdif.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index 4469cb11bf..c7a80425f0 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -217,10 +217,9 @@ MID6(uint16_t, 16) #define DIFF(type, ss) \ static unsigned diff_##ss(const type *const prev, \ const type *const next, \ - int end, int x, int k, int j) \ + int x, int y) \ { \ - return FFABS(prev[av_clip(x + k + j, 0, end)] - \ - next[av_clip(x - k + j, 0, end)]); \ + return FFABS(prev[x] - next[y]); \ } DIFF(uint8_t, 8) @@ -272,9 +271,11 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ atype sum = 0; \ \ for (int j = -redge; j <= redge; j++) { \ - sum += diff_##ss(prev_line, next_line, end, x, i, j); \ - sum += diff_##ss(prev2_line, prev_line, end, x, i, j); \ - sum += diff_##ss(next_line, next2_line, end, x, i, j); \ + const int xx = av_clip(x + i + j, 0, end); \ + const int yy = av_clip(x - i + j, 0, end); \ + sum += diff_##ss(prev_line, next_line, xx, yy); \ + sum += diff_##ss(prev2_line, prev_line, xx, yy); \ + sum += diff_##ss(next_line, next2_line, xx, yy); \ } \ \ sD[i + rslope] = sum; \ @@ -288,9 +289,11 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ atype sum = 0; \ \ for (int j = -redge; j <= redge; j++) { \ - sum += diff_##ss(prev_line, next_line, end, x, k + i, j); \ - sum += diff_##ss(prev2_line, prev_line, end, x, k + i, j); \ - sum += diff_##ss(next_line, next2_line, end, x, k + i, j); \ + const int xx = av_clip(x + k + i + j, 0, end); \ + const int yy = av_clip(x - k - i + j, 0, end); \ + sum += diff_##ss(prev_line, next_line, xx, yy); \ + sum += diff_##ss(prev2_line, prev_line, xx, yy); \ + sum += diff_##ss(next_line, next2_line, xx, yy); \ } \ \ sd[i + rslope] = sum; \ From 8a969e1280aa7aef31de6bd3db5ce46dc123fde0 Mon Sep 17 00:00:00 2001 From: songyutong Date: Tue, 9 Nov 2021 18:51:58 +0800 Subject: [PATCH 096/894] avcodec/videotoolboxenc: fix pixel buffer memory leak In function vtenc_populate_extradata(), there is a manually created pixel buffer that has not been released. So we should use CVPixelBufferRelease to release this pixel buffer at the end, otherwise will cause a memory leak. Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index bac36fda90..ebaa3ebdc8 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -2554,6 +2554,7 @@ static int vtenc_populate_extradata(AVCodecContext *avctx, pe_cleanup: + CVPixelBufferRelease(pix_buf); if(vtctx->session) CFRelease(vtctx->session); From e5199eebb44fa5b63dcec06d38cab515eaa52b6c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 11:55:51 +0100 Subject: [PATCH 097/894] avformat/apngenc: Use UINT16_MAX instead of USHRT_MAX The latter needn't be 16 bits. Signed-off-by: Andreas Rheinhardt --- libavformat/apngenc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c index c97c475274..767074ecf3 100644 --- a/libavformat/apngenc.c +++ b/libavformat/apngenc.c @@ -91,9 +91,9 @@ static int apng_write_header(AVFormatContext *format_context) return AVERROR(EINVAL); } - if (apng->last_delay.num > USHRT_MAX || apng->last_delay.den > USHRT_MAX) { + if (apng->last_delay.num > UINT16_MAX || apng->last_delay.den > UINT16_MAX) { av_reduce(&apng->last_delay.num, &apng->last_delay.den, - apng->last_delay.num, apng->last_delay.den, USHRT_MAX); + apng->last_delay.num, apng->last_delay.den, UINT16_MAX); av_log(format_context, AV_LOG_WARNING, "Last frame delay is too precise. Reducing to %d/%d (%f).\n", apng->last_delay.num, apng->last_delay.den, (double)apng->last_delay.num / apng->last_delay.den); @@ -191,7 +191,7 @@ static int flush_packet(AVFormatContext *format_context, AVPacket *packet) if (packet) { int64_t delay_num_raw = (packet->dts - apng->prev_packet->dts) * codec_stream->time_base.num; int64_t delay_den_raw = codec_stream->time_base.den; - if (!av_reduce(&delay.num, &delay.den, delay_num_raw, delay_den_raw, USHRT_MAX) && + if (!av_reduce(&delay.num, &delay.den, delay_num_raw, delay_den_raw, UINT16_MAX) && !apng->framerate_warned) { av_log(format_context, AV_LOG_WARNING, "Frame rate is too high or specified too precisely. Unable to copy losslessly.\n"); @@ -281,9 +281,9 @@ static void apng_deinit(AVFormatContext *s) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "plays", "Number of times to play the output: 0 - infinite loop, 1 - no loop", OFFSET(plays), - AV_OPT_TYPE_INT, { .i64 = 1 }, 0, UINT_MAX, ENC }, + AV_OPT_TYPE_INT, { .i64 = 1 }, 0, UINT16_MAX, ENC }, { "final_delay", "Force delay after the last frame", OFFSET(last_delay), - AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, USHRT_MAX, ENC }, + AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, UINT16_MAX, ENC }, { NULL }, }; From 6f1130be7880dc9e5e7c812f377dc3e480580704 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 14:50:27 +0100 Subject: [PATCH 098/894] avcodec/libx264: Check for overflow if necessary Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 0766b4a950..8711c72131 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -138,13 +138,23 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, { X264Context *x4 = ctx->priv_data; uint8_t *p; - int i, size = x4->sei_size, ret; + uint64_t size = x4->sei_size; + int i; + int ret; if (!nnal) return 0; - for (i = 0; i < nnal; i++) + for (int i = 0; i < nnal; i++) { size += nals[i].i_payload; + /* ff_get_encode_buffer() accepts an int64_t and + * so we need to make sure that no overflow happens before + * that. With 32bit ints this is automatically true. */ +#if INT_MAX > INT64_MAX / INT_MAX - 1 + if ((int64_t)size < 0) + return AVERROR(ERANGE); +#endif + } if ((ret = ff_get_encode_buffer(ctx, pkt, size, 0)) < 0) return ret; From 19ed9236db8796104c5a4f3343596172b01ebd1b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 14:56:01 +0100 Subject: [PATCH 099/894] avcodec/libx264: Remove always-false checks Always false since this encoder was switched to encode2 and ff_alloc_packet() in 06484d0b8a7d4d1a694ba7ab277e2ec32d6558d7 and f2b20b7a8b6fcbcd8cc669f5211e4e2ed7d8e9f3. Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 8711c72131..4fe02dd11c 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -162,11 +162,7 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, p = pkt->data; /* Write the SEI as part of the first frame. */ - if (x4->sei_size > 0 && nnal > 0) { - if (x4->sei_size > size) { - av_log(ctx, AV_LOG_ERROR, "Error: nal buffer is too small\n"); - return -1; - } + if (x4->sei_size > 0) { memcpy(p, x4->sei, x4->sei_size); p += x4->sei_size; x4->sei_size = 0; From b59138b6819b97544fd2fc40a27fdac0d75b2287 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 15:18:41 +0100 Subject: [PATCH 100/894] avcodec/libx264: Simplify copying packet data x264.h: "the payloads of all output NALs are guaranteed to be sequential in memory." Therefore we can omit the loop. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 4fe02dd11c..5f62c7b1d8 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -139,7 +139,6 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, X264Context *x4 = ctx->priv_data; uint8_t *p; uint64_t size = x4->sei_size; - int i; int ret; if (!nnal) @@ -165,14 +164,14 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, if (x4->sei_size > 0) { memcpy(p, x4->sei, x4->sei_size); p += x4->sei_size; + size -= x4->sei_size; x4->sei_size = 0; av_freep(&x4->sei); } - for (i = 0; i < nnal; i++){ - memcpy(p, nals[i].p_payload, nals[i].i_payload); - p += nals[i].i_payload; - } + /* x264 guarantees the payloads of the NALs + * to be sequential in memory. */ + memcpy(p, nals[0].p_payload, size); return 1; } From ddd701fbbf71a85711bbb1fc52f5de86cdca1261 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 08:28:28 +0100 Subject: [PATCH 101/894] avcodec/speexdec: Remove dead code Fixes Coverity issue #1492840. Signed-off-by: Andreas Rheinhardt --- libavcodec/speexdec.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c index 4c50f54f27..90e95f0785 100644 --- a/libavcodec/speexdec.c +++ b/libavcodec/speexdec.c @@ -1221,7 +1221,7 @@ static int sb_decode(AVCodecContext *avctx, void *ptr_st, float low_pi_gain[NB_NB_SUBFRAMES]; float low_exc_rms[NB_NB_SUBFRAMES]; float interp_qlsp[NB_ORDER]; - int ret, wideband, dtx = 0; + int ret, wideband; float *low_innov_alias; float qlsp[NB_ORDER]; float ak[NB_ORDER]; @@ -1254,11 +1254,6 @@ static int sb_decode(AVCodecContext *avctx, void *ptr_st, /* If null mode (no transmission), just set a couple things to zero */ if (st->submodes[st->submodeID] == NULL) { - if (dtx) { - //sb_decode_lost(st, out, 1); - return 0; - } - for (int i = 0; i < st->frame_size; i++) out[st->frame_size + i] = 1e-15f; From 945b2dcc631a891fcc8c911891fd6730a40b8248 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 08:35:08 +0100 Subject: [PATCH 102/894] avformat/hls_sample_encryption: Fix precedence Fixes Coverity ticket #1492869. Reviewed-by: Steven Liu Signed-off-by: Andreas Rheinhardt --- libavformat/hls_sample_encryption.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hls_sample_encryption.c b/libavformat/hls_sample_encryption.c index 396fe97921..38795c7fb0 100644 --- a/libavformat/hls_sample_encryption.c +++ b/libavformat/hls_sample_encryption.c @@ -268,7 +268,7 @@ static int get_next_adts_frame(CodecParserContext *ctx, AudioFrame *frame) /* Find next sync word 0xFFF */ while (ctx->buf_ptr < ctx->buf_end - 1) { - if (*ctx->buf_ptr == 0xFF && *(ctx->buf_ptr + 1) & 0xF0 == 0xF0) + if (*ctx->buf_ptr == 0xFF && (*(ctx->buf_ptr + 1) & 0xF0) == 0xF0) break; ctx->buf_ptr++; } From 44c65c6cc0ba3a08834b7c4d83cb5f56321f914d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 8 Nov 2021 18:53:41 +0100 Subject: [PATCH 103/894] fftools/ffmpeg_opt: Fix copyinkf option name in warning message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 7aff43d917..ab4c63a362 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -79,7 +79,7 @@ static const char *const opt_name_inter_matrices[] = {"inter_matrix", static const char *const opt_name_chroma_intra_matrices[] = {"chroma_intra_matrix", NULL}; static const char *const opt_name_top_field_first[] = {"top", NULL}; static const char *const opt_name_presets[] = {"pre", "apre", "vpre", "spre", NULL}; -static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkfr", NULL}; +static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkf", NULL}; static const char *const opt_name_copy_prior_start[] = {"copypriorss", NULL}; static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; From 9fd2b39428165c2319106e82a3c1ca1bba11aa54 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 10 Nov 2021 23:36:15 +0800 Subject: [PATCH 104/894] avutil/opt: handle whole range of int64_t in av_opt_get_int Make get_int/set_int symetric. The int64_t to double to int64_t conversion is unprecise for large value. Signed-off-by: Michael Niedermayer --- libavutil/opt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index c7001dbcd3..cfda31ea2f 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -920,7 +920,10 @@ int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_v if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) return ret; - *out_val = num * intnum / den; + if (num == den) + *out_val = intnum; + else + *out_val = num * intnum / den; return 0; } From afcf226b337584f5028265b361d8a5a930696a31 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 5 Nov 2021 20:32:15 +0800 Subject: [PATCH 105/894] avfilter/af_atilt: use ff_filter_execute() Signed-off-by: Limin Wang --- libavfilter/af_atilt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_atilt.c b/libavfilter/af_atilt.c index a1ce030feb..a6f7782af5 100644 --- a/libavfilter/af_atilt.c +++ b/libavfilter/af_atilt.c @@ -196,7 +196,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } td.in = in; td.out = out; - ctx->internal->execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels, + ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); if (out != in) From 946493eb3e072b499909f606625480c928834a44 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 11 Nov 2021 09:48:07 +0100 Subject: [PATCH 106/894] avcodec/mlpdec: cover case when >2 channels are in single substream Previously it was assumed that all >2 channels streams have >1 substreams. --- libavcodec/mlpdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 68c270ef52..780ed5b7b6 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -417,7 +417,8 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->substream[2].mask = mh.channel_layout_thd_stream2; else m->substream[2].mask = mh.channel_layout_thd_stream1; - m->substream[1].mask = mh.channel_layout_thd_stream1; + if (m->avctx->channels > 2) + m->substream[mh.num_substreams > 1].mask = mh.channel_layout_thd_stream1; if (m->avctx->channels<=2 && m->substream[substr].mask == AV_CH_LAYOUT_MONO && m->max_decoded_substream == 1) { av_log(m->avctx, AV_LOG_DEBUG, "Mono stream with 2 substreams, ignoring 2nd\n"); From aebdffb9c5d67171a53be16dbf6649f5f02fb225 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Nov 2021 10:19:27 +0100 Subject: [PATCH 107/894] avfilter/vf_estdif: allow to change two more options --- doc/filters.texi | 8 ++++++++ libavfilter/vf_estdif.c | 15 ++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 5ebfc11237..06aa3594d5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11711,6 +11711,14 @@ Allowed range is from 1 to 15. Specify the search radius for best edge matching. Default value is 2. Allowed range is from 0 to 15. +@item ecost +Specify the edge cost for edge matching. Default value is 0.03125. +Allowed range is from 0 to 1. + +@item mcost +Specify the middle cost for edge matching. Default value is 0.5. +Allowed range is from 0 to 1. + @item dcost Specify the distance cost for edge matching. Default value is 0.5. Allowed range is from 0 to 1. diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index c7a80425f0..0e5c9b4224 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -35,6 +35,8 @@ typedef struct ESTDIFContext { int deint; ///< which frames to deinterlace int rslope; ///< best edge slope search radius int redge; ///< best edge match search radius + float ecost; ///< edge cost for edge matching + float mcost; ///< middle cost for edge matching float dcost; ///< distance cost for edge matching int interp; ///< type of interpolation int linesize[4]; ///< bytes of pixel data per line for each plane @@ -93,6 +95,8 @@ static const AVOption estdif_options[] = { CONST("interlaced", "only deinterlace frames marked as interlaced", 1, "deint"), { "rslope", "specify the search radius for edge slope tracing", OFFSET(rslope), AV_OPT_TYPE_INT, {.i64=1}, 1, MAX_R, FLAGS, }, { "redge", "specify the search radius for best edge matching", OFFSET(redge), AV_OPT_TYPE_INT, {.i64=2}, 0, MAX_R, FLAGS, }, + { "ecost", "specify the edge cost for edge matching", OFFSET(ecost), AV_OPT_TYPE_FLOAT,{.dbl=0.03125},0,1,FLAGS, }, + { "mcost", "specify the middle cost for edge matching", OFFSET(mcost), AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, FLAGS, }, { "dcost", "specify the distance cost for edge matching", OFFSET(dcost), AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, FLAGS, }, { "interp", "specify the type of interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, FLAGS, "interp" }, CONST("2p", "two-point interpolation", 0, "interp"), @@ -260,9 +264,10 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const type *const next2_line = (const type *const)nnext2_line; \ const type *const next3_line = (const type *const)nnext3_line; \ const int interp = s->interp; \ + const int ecost = s->ecost * 32.f; \ const int dcost = s->dcost * s->max; \ const int end = width - 1; \ - const atype f = redge + 2; \ + const atype mcost = s->mcost * s->redge * 4.f; \ atype sd[S], sD[S], di = 0; \ atype dmin = amax; \ int k = *K; \ @@ -278,8 +283,8 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ sum += diff_##ss(next_line, next2_line, xx, yy); \ } \ \ - sD[i + rslope] = sum; \ - sD[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, i); \ + sD[i + rslope] = ecost * sum; \ + sD[i + rslope] += mcost * cost_##ss(prev_line, next_line, end, x, i);\ sD[i + rslope] += dcost * abs(i); \ \ dmin = FFMIN(sD[i + rslope], dmin); \ @@ -296,8 +301,8 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ sum += diff_##ss(next_line, next2_line, xx, yy); \ } \ \ - sd[i + rslope] = sum; \ - sd[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, k + i); \ + sd[i + rslope] = ecost * sum; \ + sd[i + rslope] += mcost * cost_##ss(prev_line, next_line, end, x, k+i);\ sd[i + rslope] += dcost * abs(k + i); \ \ dmin = FFMIN(sd[i + rslope], dmin); \ From 047c362d3cd71605628dc510e0b8747310f1db86 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Oct 2021 17:13:34 +0200 Subject: [PATCH 108/894] avfilter/vf_nlmeans: add x86 SIMD --- libavfilter/vf_nlmeans.c | 9 ++- libavfilter/vf_nlmeans.h | 1 + libavfilter/x86/Makefile | 2 + libavfilter/x86/vf_nlmeans.asm | 97 +++++++++++++++++++++++++++++++ libavfilter/x86/vf_nlmeans_init.c | 40 +++++++++++++ 5 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 libavfilter/x86/vf_nlmeans.asm create mode 100644 libavfilter/x86/vf_nlmeans_init.c diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index dee1f68101..8a05965c9b 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -308,9 +308,9 @@ static int config_input(AVFilterLink *inlink) s->ii = s->ii_orig + s->ii_lz_32 + 1; // allocate weighted average for every pixel - s->linesize = inlink->w; - s->total_weight = av_malloc_array(inlink->w, inlink->h * sizeof(*s->total_weight)); - s->sum = av_malloc_array(inlink->w, inlink->h * sizeof(*s->sum)); + s->linesize = inlink->w + 100; + s->total_weight = av_malloc_array(s->linesize, inlink->h * sizeof(*s->total_weight)); + s->sum = av_malloc_array(s->linesize, inlink->h * sizeof(*s->sum)); if (!s->total_weight || !s->sum) return AVERROR(ENOMEM); @@ -519,6 +519,9 @@ void ff_nlmeans_init(NLMeansDSPContext *dsp) if (ARCH_AARCH64) ff_nlmeans_init_aarch64(dsp); + + if (ARCH_X86) + ff_nlmeans_init_x86(dsp); } static av_cold int init(AVFilterContext *ctx) diff --git a/libavfilter/vf_nlmeans.h b/libavfilter/vf_nlmeans.h index cd1ee7c0bf..43611a03bd 100644 --- a/libavfilter/vf_nlmeans.h +++ b/libavfilter/vf_nlmeans.h @@ -41,5 +41,6 @@ typedef struct NLMeansDSPContext { void ff_nlmeans_init(NLMeansDSPContext *dsp); void ff_nlmeans_init_aarch64(NLMeansDSPContext *dsp); +void ff_nlmeans_init_x86(NLMeansDSPContext *dsp); #endif /* AVFILTER_NLMEANS_H */ diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index a29941eaeb..e87481bd7a 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -20,6 +20,7 @@ OBJS-$(CONFIG_LIMITER_FILTER) += x86/vf_limiter_init.o OBJS-$(CONFIG_LUT3D_FILTER) += x86/vf_lut3d_init.o OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp_init.o OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge_init.o +OBJS-$(CONFIG_NLMEANS_FILTER) += x86/vf_nlmeans_init.o OBJS-$(CONFIG_NOISE_FILTER) += x86/vf_noise.o OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay_init.o OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7_init.o @@ -61,6 +62,7 @@ X86ASM-OBJS-$(CONFIG_LIMITER_FILTER) += x86/vf_limiter.o X86ASM-OBJS-$(CONFIG_LUT3D_FILTER) += x86/vf_lut3d.o X86ASM-OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp.o X86ASM-OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge.o +X86ASM-OBJS-$(CONFIG_NLMEANS_FILTER) += x86/vf_nlmeans.o X86ASM-OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay.o X86ASM-OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7.o X86ASM-OBJS-$(CONFIG_PSNR_FILTER) += x86/vf_psnr.o diff --git a/libavfilter/x86/vf_nlmeans.asm b/libavfilter/x86/vf_nlmeans.asm new file mode 100644 index 0000000000..8f57801035 --- /dev/null +++ b/libavfilter/x86/vf_nlmeans.asm @@ -0,0 +1,97 @@ +;***************************************************************************** +;* x86-optimized functions for nlmeans filter +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + + +%include "libavutil/x86/x86util.asm" + +%if HAVE_AVX2_EXTERNAL && ARCH_X86_64 + +SECTION_RODATA 32 + +ending_lut: dd -1, -1, -1, -1, -1, -1, -1, -1,\ + 0, -1, -1, -1, -1, -1, -1, -1,\ + 0, 0, -1, -1, -1, -1, -1, -1,\ + 0, 0, 0, -1, -1, -1, -1, -1,\ + 0, 0, 0, 0, -1, -1, -1, -1,\ + 0, 0, 0, 0, 0, -1, -1, -1,\ + 0, 0, 0, 0, 0, 0, -1, -1,\ + 0, 0, 0, 0, 0, 0, 0, -1,\ + 0, 0, 0, 0, 0, 0, 0, 0 + +SECTION .text + +; void ff_compute_weights_line(const uint32_t *const iia, +; const uint32_t *const iib, +; const uint32_t *const iid, +; const uint32_t *const iie, +; const uint8_t *const src, +; float *total, +; float *sum, +; const float *const lut, +; int max, +; int startx, int endx); + +INIT_YMM avx2 +cglobal compute_weights_line, 8, 13, 5, 0, iia, iib, iid, iie, src, total, sum, lut, x, startx, endx, mod, elut + movsxd startxq, dword startxm + movsxd endxq, dword endxm + VPBROADCASTD m2, r8m + + mov xq, startxq + mov modq, mmsize / 4 + lea elutq, [ending_lut] + + vpcmpeqd m4, m4 + + .loop: + mov startxq, endxq + sub startxq, xq + cmp startxq, modq + cmovge startxq, modq + sal startxq, 5 + + movu m0, [iieq + xq * 4] + + psubd m0, [iidq + xq * 4] + psubd m0, [iibq + xq * 4] + paddd m0, [iiaq + xq * 4] + por m0, [elutq + startxq] + pminud m0, m2 + pslld m0, 2 + mova m3, m4 + vgatherdps m1, [lutq + m0], m3 + + pmovzxbd m0, [srcq + xq] + cvtdq2ps m0, m0 + + mulps m0, m1 + + addps m1, [totalq + xq * 4] + addps m0, [sumq + xq * 4] + + movups [totalq + xq * 4], m1 + movups [sumq + xq * 4], m0 + + add xq, mmsize / 4 + cmp xq, endxq + jl .loop + RET + +%endif diff --git a/libavfilter/x86/vf_nlmeans_init.c b/libavfilter/x86/vf_nlmeans_init.c new file mode 100644 index 0000000000..37764d30ab --- /dev/null +++ b/libavfilter/x86/vf_nlmeans_init.c @@ -0,0 +1,40 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/vf_nlmeans.h" + +void ff_compute_weights_line_avx2(const uint32_t *const iia, + const uint32_t *const iib, + const uint32_t *const iid, + const uint32_t *const iie, + const uint8_t *const src, + float *total_weight, + float *sum, + const float *const weight_lut, + int max_meaningful_diff, + int startx, int endx); + +av_cold void ff_nlmeans_init_x86(NLMeansDSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (ARCH_X86_64 && EXTERNAL_AVX2_FAST(cpu_flags)) + dsp->compute_weights_line = ff_compute_weights_line_avx2; +} From 7f3878828d88c6a8287d54818659e6f70293dabb Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 11 Oct 2021 00:20:15 +0200 Subject: [PATCH 109/894] hwcontext_vulkan: bump required Vulkan loader version to 1.2 --- configure | 6 +++--- libavutil/hwcontext_vulkan.c | 2 +- libavutil/hwcontext_vulkan.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure b/configure index c01aa480c7..103829e688 100755 --- a/configure +++ b/configure @@ -6824,10 +6824,10 @@ enabled vdpau && enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd if enabled vulkan; then - require_pkg_config_cpp vulkan "vulkan >= 1.1.97" "vulkan/vulkan.h" "defined VK_VERSION_1_1" || - require_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_1" + require_pkg_config_cpp vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || + require_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_2" # vulkan_lib should be removed once glslang filters are updated - check_pkg_config vulkan_lib "vulkan >= 1.1.97" "vulkan/vulkan.h" vkCreateInstance + check_pkg_config vulkan_lib "vulkan >= 1.2.189" "vulkan/vulkan.h" vkCreateInstance fi if enabled x86; then diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 2c3216857a..570ebf23bb 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -676,7 +676,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) VkApplicationInfo application_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pEngineName = "libavutil", - .apiVersion = VK_API_VERSION_1_1, + .apiVersion = VK_API_VERSION_1_2, .engineVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO), diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index e4645527d7..8d1ae50e65 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -50,7 +50,7 @@ typedef struct AVVulkanDeviceContext { PFN_vkGetInstanceProcAddr get_proc_addr; /** - * Vulkan instance. Must be at least version 1.1. + * Vulkan instance. Must be at least version 1.2. */ VkInstance inst; From 00ef53c3eabb0e99fd9b62dfd30992824de27e23 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 4 Nov 2021 12:17:06 +0100 Subject: [PATCH 110/894] hwcontext_vulkan: switch to using timeline semaphores --- libavutil/hwcontext_vulkan.c | 91 ++++++++++++++++++++++++++++++++---- libavutil/hwcontext_vulkan.h | 13 +++++- 2 files changed, 92 insertions(+), 12 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 570ebf23bb..3765dd632b 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -74,7 +74,7 @@ enum VulkanExtensions { /* Device */ \ MACRO(1, 0, EXT_NO_FLAG, GetDeviceProcAddr) \ MACRO(1, 0, EXT_NO_FLAG, CreateDevice) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFeatures) \ + MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ MACRO(1, 0, EXT_NO_FLAG, DestroyDevice) \ \ MACRO(1, 0, EXT_NO_FLAG, EnumeratePhysicalDevices) \ @@ -198,6 +198,10 @@ typedef struct VulkanDevicePriv { VkPhysicalDeviceMemoryProperties mprops; VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops; + /* Features */ + VkPhysicalDeviceVulkan11Features device_features_1_1; + VkPhysicalDeviceVulkan12Features device_features_1_2; + /* Queues */ uint32_t qfs[3]; int num_qfs; @@ -1176,7 +1180,7 @@ err: } static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, - VkSubmitInfo *s_info, int synchronous) + VkSubmitInfo *s_info, AVVkFrame *f, int synchronous) { VkResult ret; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; @@ -1200,6 +1204,10 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, return AVERROR_EXTERNAL; } + if (f) + for (int i = 0; i < s_info->signalSemaphoreCount; i++) + f->sem_value[i]++; + q->was_synchronous = synchronous; if (synchronous) { @@ -1250,7 +1258,17 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDevicePriv *p = ctx->internal->priv; VulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - VkPhysicalDeviceFeatures dev_features = { 0 }; + VkPhysicalDeviceVulkan12Features dev_features_1_2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + }; + VkPhysicalDeviceVulkan11Features dev_features_1_1 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, + .pNext = &dev_features_1_2, + }; + VkPhysicalDeviceFeatures2 dev_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + .pNext = &dev_features_1_1, + }; VkDeviceQueueCreateInfo queue_create_info[3] = { { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, @@ -1265,6 +1283,10 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, }; hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + hwctx->device_features.pNext = &p->device_features_1_1; + p->device_features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + p->device_features_1_1.pNext = &p->device_features_1_2; + p->device_features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; ctx->free = vulkan_device_free; /* Create an instance if not given one */ @@ -1275,10 +1297,10 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if ((err = find_device(ctx, dev_select))) goto end; - vk->GetPhysicalDeviceFeatures(hwctx->phys_dev, &dev_features); + vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &dev_features); /* Try to keep in sync with libplacebo */ -#define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.NAME; +#define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.features.NAME; COPY_FEATURE(hwctx->device_features, shaderImageGatherExtended) COPY_FEATURE(hwctx->device_features, shaderStorageImageReadWithoutFormat) COPY_FEATURE(hwctx->device_features, shaderStorageImageWriteWithoutFormat) @@ -1287,6 +1309,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, COPY_FEATURE(hwctx->device_features, shaderInt64) #undef COPY_FEATURE + /* We require timeline semaphores */ + if (!dev_features_1_2.timelineSemaphore) { + av_log(ctx, AV_LOG_ERROR, "Device does not support timeline semaphores!\n"); + err = AVERROR(ENOSYS); + } + p->device_features_1_2.timelineSemaphore = 1; + /* Search queue family */ if ((err = search_queue_families(ctx, &dev_info))) goto end; @@ -1732,18 +1761,28 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; VulkanFunctions *vk = &p->vkfn; + uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pSignalSemaphoreValues = sem_sig_val, + .signalSemaphoreValueCount = planes, + }; + VkSubmitInfo s_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, .pSignalSemaphores = frame->sem, .signalSemaphoreCount = planes, }; VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; - for (int i = 0; i < planes; i++) + for (int i = 0; i < planes; i++) { wait_st[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + sem_sig_val[i] = frame->sem_value[i] + 1; + } switch (pmode) { case PREP_MODE_WRITE: @@ -1760,6 +1799,8 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, new_layout = VK_IMAGE_LAYOUT_GENERAL; new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; + s_timeline_sem_info.pWaitSemaphoreValues = frame->sem_value; + s_timeline_sem_info.waitSemaphoreValueCount = planes; s_info.pWaitSemaphores = frame->sem; s_info.pWaitDstStageMask = wait_st; s_info.waitSemaphoreCount = planes; @@ -1794,7 +1835,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, planes, img_bar); - return submit_exec_ctx(hwfc, ectx, &s_info, 0); + return submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); } static inline void get_plane_wh(int *w, int *h, enum AVPixelFormat format, @@ -1833,9 +1874,16 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, }; + VkSemaphoreTypeCreateInfo sem_type_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + .pNext = p->extensions & EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 0, + }; + VkSemaphoreCreateInfo sem_spawn = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = p->extensions & EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, + .pNext = &sem_type_info, }; AVVkFrame *f = av_vk_frame_alloc(); @@ -1888,6 +1936,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, f->layout[i] = create_info.initialLayout; f->access[i] = 0x0; + f->sem_value[i] = 0; } f->flags = 0x0; @@ -2315,8 +2364,15 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f .handleTypes = htype, }; + VkSemaphoreTypeCreateInfo sem_type_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 1, + }; + VkSemaphoreCreateInfo sem_spawn = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &sem_type_info, }; VkImageCreateInfo create_info = { @@ -2374,6 +2430,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f f->layout[i] = create_info.initialLayout; f->access[i] = 0x0; + f->sem_value[i] = 0; } for (int i = 0; i < desc->nb_objects; i++) { @@ -3224,8 +3281,19 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, VulkanExecCtx *ectx = to_buf ? &fp->download_ctx : &fp->upload_ctx; VkCommandBuffer cmd_buf = get_buf_exec_ctx(hwfc, ectx); + uint64_t sem_signal_values[AV_NUM_DATA_POINTERS]; + + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pWaitSemaphoreValues = frame->sem_value, + .pSignalSemaphoreValues = sem_signal_values, + .waitSemaphoreValueCount = planes, + .signalSemaphoreValueCount = planes, + }; + VkSubmitInfo s_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, .pSignalSemaphores = frame->sem, .pWaitSemaphores = frame->sem, .pWaitDstStageMask = sem_wait_dst, @@ -3233,6 +3301,9 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, .waitSemaphoreCount = planes, }; + for (int i = 0; i < planes; i++) + sem_signal_values[i] = frame->sem_value[i] + 1; + if ((err = wait_start_exec_ctx(hwfc, ectx))) return err; @@ -3313,9 +3384,9 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, } if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, planes))) return err; - return submit_exec_ctx(hwfc, ectx, &s_info, !ref); + return submit_exec_ctx(hwfc, ectx, &s_info, frame, !ref); } else { - return submit_exec_ctx(hwfc, ectx, &s_info, 1); + return submit_exec_ctx(hwfc, ectx, &s_info, frame, 1); } } diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 8d1ae50e65..9ac01e3b46 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -195,13 +195,22 @@ typedef struct AVVkFrame { VkImageLayout layout[AV_NUM_DATA_POINTERS]; /** - * Synchronization semaphores. Must not be freed manually. Must be waited on - * and signalled at every queue submission. + * Synchronization timeline semaphores. Must not be freed manually. + * Must be waited on at every submission using the value in sem_value, + * and must be signalled at every submission, using an incremented value. + * * Could be less than the amount of images: either one per VkDeviceMemory * or one for the entire frame. All others will be set to VK_NULL_HANDLE. */ VkSemaphore sem[AV_NUM_DATA_POINTERS]; + /** + * Up to date semaphore value at which each image becomes accessible. + * Clients must wait on this value when submitting a command queue, + * and increment it when signalling. + */ + uint64_t sem_value[AV_NUM_DATA_POINTERS]; + /** * Internal data. */ From 0370a580dc9210450bf24d71e34966fabcda8747 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 5 Nov 2021 06:55:42 +0100 Subject: [PATCH 111/894] hwcontext_vulkan: fix mapping from/to DRM/VAAPI frames --- libavutil/hwcontext_vulkan.c | 205 +++++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 84 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 3765dd632b..eb7ced5a25 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2011,7 +2011,7 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); @@ -2323,13 +2323,9 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f VulkanDevicePriv *p = ctx->internal->priv; VulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; - AVVulkanFramesContext *frames_hwctx = hwfc->hwctx; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; - const int has_modifiers = !!(p->extensions & EXT_DRM_MODIFIER_FLAGS); - VkSubresourceLayout plane_data[AV_NUM_DATA_POINTERS] = { 0 }; - VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { 0 }; - VkBindImagePlaneMemoryInfo plane_info[AV_NUM_DATA_POINTERS] = { 0 }; - VkExternalMemoryHandleTypeFlagBits htype = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; + VkBindImagePlaneMemoryInfo plane_info[AV_DRM_MAX_PLANES]; for (int i = 0; i < desc->nb_layers; i++) { if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) { @@ -2345,48 +2341,48 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f goto fail; } - f->tiling = has_modifiers ? VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : - desc->objects[0].format_modifier == DRM_FORMAT_MOD_LINEAR ? - VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; + f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; for (int i = 0; i < desc->nb_layers; i++) { const int planes = desc->layers[i].nb_planes; - VkImageDrmFormatModifierExplicitCreateInfoEXT drm_info = { - .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT, - .drmFormatModifier = desc->objects[0].format_modifier, - .drmFormatModifierPlaneCount = planes, - .pPlaneLayouts = (const VkSubresourceLayout *)&plane_data, - }; - - VkExternalMemoryImageCreateInfo einfo = { - .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, - .pNext = has_modifiers ? &drm_info : NULL, - .handleTypes = htype, - }; + /* Semaphore */ VkSemaphoreTypeCreateInfo sem_type_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, - .initialValue = 1, + .initialValue = 0, }; - VkSemaphoreCreateInfo sem_spawn = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, .pNext = &sem_type_info, }; + /* Image creation */ + VkSubresourceLayout ext_img_layouts[AV_DRM_MAX_PLANES]; + VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = { + .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT, + .drmFormatModifier = desc->objects[0].format_modifier, + .drmFormatModifierPlaneCount = planes, + .pPlaneLayouts = (const VkSubresourceLayout *)&ext_img_layouts, + }; + VkExternalMemoryImageCreateInfo ext_img_spec = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .pNext = &ext_img_mod_spec, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; VkImageCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = &einfo, + .pNext = &ext_img_spec, .imageType = VK_IMAGE_TYPE_2D, .format = drm_to_vulkan_fmt(desc->layers[i].format), .extent.depth = 1, .mipLevels = 1, .arrayLayers = 1, - .flags = VK_IMAGE_CREATE_ALIAS_BIT, + .flags = 0x0, /* ALIAS flag is implicit for imported images */ .tiling = f->tiling, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */ - .usage = frames_hwctx->usage, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT, .samples = VK_SAMPLE_COUNT_1_BIT, .pQueueFamilyIndices = p->qfs, .queueFamilyIndexCount = p->num_qfs, @@ -2394,15 +2390,53 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f VK_SHARING_MODE_EXCLUSIVE, }; + /* Image format verification */ + VkImageFormatProperties2 props_ret = { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + }; + VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, + .drmFormatModifier = ext_img_mod_spec.drmFormatModifier, + .pQueueFamilyIndices = create_info.pQueueFamilyIndices, + .queueFamilyIndexCount = create_info.queueFamilyIndexCount, + .sharingMode = create_info.sharingMode, + }; + VkPhysicalDeviceExternalImageFormatInfo props_ext = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + .pNext = &props_drm_mod, + .handleType = ext_img_spec.handleTypes, + }; + VkPhysicalDeviceImageFormatInfo2 fmt_props = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + .pNext = &props_ext, + .format = create_info.format, + .type = create_info.imageType, + .tiling = create_info.tiling, + .usage = create_info.usage, + .flags = create_info.flags, + }; + + /* Check if importing is possible for this combination of parameters */ + ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev, + &fmt_props, &props_ret); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Cannot map DRM frame to Vulkan: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Set the image width/height */ get_plane_wh(&create_info.extent.width, &create_info.extent.height, hwfc->sw_format, src->width, src->height, i); + /* Set the subresource layout based on the layer properties */ for (int j = 0; j < planes; j++) { - plane_data[j].offset = desc->layers[i].planes[j].offset; - plane_data[j].rowPitch = desc->layers[i].planes[j].pitch; - plane_data[j].size = 0; /* The specs say so for all 3 */ - plane_data[j].arrayPitch = 0; - plane_data[j].depthPitch = 0; + ext_img_layouts[j].offset = desc->layers[i].planes[j].offset; + ext_img_layouts[j].rowPitch = desc->layers[i].planes[j].pitch; + ext_img_layouts[j].size = 0; /* The specs say so for all 3 */ + ext_img_layouts[j].arrayPitch = 0; + ext_img_layouts[j].depthPitch = 0; } /* Create image */ @@ -2434,24 +2468,37 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f } for (int i = 0; i < desc->nb_objects; i++) { - int use_ded_mem = 0; + /* Memory requirements */ + VkImageMemoryRequirementsInfo2 req_desc = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + .image = f->img[i], + }; + VkMemoryDedicatedRequirements ded_req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + }; + VkMemoryRequirements2 req2 = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + .pNext = &ded_req, + }; + + /* Allocation/importing */ VkMemoryFdPropertiesKHR fdmp = { .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR, }; - VkMemoryRequirements req = { - .size = desc->objects[i].size, - }; VkImportMemoryFdInfoKHR idesc = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, - .handleType = htype, .fd = dup(desc->objects[i].fd), + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; VkMemoryDedicatedAllocateInfo ded_alloc = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, .pNext = &idesc, + .image = req_desc.image, }; - ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev, htype, + /* Get object properties */ + ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, idesc.fd, &fdmp); if (ret != VK_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n", @@ -2461,59 +2508,44 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f goto fail; } - req.memoryTypeBits = fdmp.memoryTypeBits; + vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2); - /* Dedicated allocation only makes sense if there's a one to one mapping - * between images and the memory backing them, so only check in this - * case. */ - if (desc->nb_layers == desc->nb_objects) { - VkImageMemoryRequirementsInfo2 req_desc = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, - .image = f->img[i], - }; - VkMemoryDedicatedRequirements ded_req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - }; - VkMemoryRequirements2 req2 = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &ded_req, - }; + /* Only a single bit must be set, not a range, and it must match */ + req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits; - vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2); - - use_ded_mem = ded_req.prefersDedicatedAllocation | - ded_req.requiresDedicatedAllocation; - if (use_ded_mem) - ded_alloc.image = f->img[i]; - } - - err = alloc_mem(ctx, &req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - use_ded_mem ? &ded_alloc : ded_alloc.pNext, + err = alloc_mem(ctx, &req2.memoryRequirements, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + (ded_req.prefersDedicatedAllocation || + ded_req.requiresDedicatedAllocation) ? + &ded_alloc : ded_alloc.pNext, &f->flags, &f->mem[i]); if (err) { close(idesc.fd); return err; } - f->size[i] = desc->objects[i].size; + f->size[i] = req2.memoryRequirements.size; } for (int i = 0; i < desc->nb_layers; i++) { const int planes = desc->layers[i].nb_planes; - const int signal_p = has_modifiers && (planes > 1); for (int j = 0; j < planes; j++) { VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT : j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT : VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT; plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; + plane_info[bind_counts].pNext = NULL; plane_info[bind_counts].planeAspect = aspect; bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; - bind_info[bind_counts].pNext = signal_p ? &plane_info[bind_counts] : NULL; + bind_info[bind_counts].pNext = planes > 1 ? &plane_info[bind_counts] : NULL; bind_info[bind_counts].image = f->img[i]; bind_info[bind_counts].memory = f->mem[desc->layers[i].planes[j].object_index]; - bind_info[bind_counts].memoryOffset = desc->layers[i].planes[j].offset; + + /* Offset is already signalled via pPlaneLayouts above */ + bind_info[bind_counts].memoryOffset = 0; + bind_counts++; } } @@ -2523,7 +2555,8 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", vk_ret2str(ret)); - return AVERROR_EXTERNAL; + err = AVERROR_EXTERNAL; + goto fail; } /* NOTE: This is completely uneccesary and unneeded once we can import @@ -2848,12 +2881,16 @@ static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, #if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_vaapi(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #endif case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_drm(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #endif default: return AVERROR(ENOSYS); @@ -2911,14 +2948,12 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, if (err < 0) goto end; - if (p->extensions & EXT_DRM_MODIFIER_FLAGS) { - ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0], - &drm_mod); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n"); - err = AVERROR_EXTERNAL; - goto end; - } + ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0], + &drm_mod); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n"); + err = AVERROR_EXTERNAL; + goto end; } for (int i = 0; (i < planes) && (f->mem[i]); i++) { @@ -2945,9 +2980,7 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, for (int i = 0; i < drm_desc->nb_layers; i++) { VkSubresourceLayout layout; VkImageSubresource sub = { - .aspectMask = p->extensions & EXT_DRM_MODIFIER_FLAGS ? - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT : - VK_IMAGE_ASPECT_COLOR_BIT, + .aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, }; VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i]; @@ -3019,12 +3052,16 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_LIBDRM case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_drm(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_vaapi(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #endif #endif default: From 09e4687b5b8e0ad690f7e101e539c0605768d1d7 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 5 Nov 2021 13:50:32 +0100 Subject: [PATCH 112/894] hwcontext_vulkan: port CUDA interop to use timeline semaphores --- libavutil/hwcontext_vulkan.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index eb7ced5a25..ee2e5663b7 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -18,6 +18,8 @@ #define VK_NO_PROTOTYPES +#include + #include "config.h" #include "pixdesc.h" #include "avstring.h" @@ -33,7 +35,6 @@ #endif #if CONFIG_LIBDRM -#include #include #include #include "hwcontext_drm.h" @@ -237,6 +238,7 @@ typedef struct AVVkFrameInternal { CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS]; CUarray cu_array[AV_NUM_DATA_POINTERS]; CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS]; + int exp_sem[AV_NUM_DATA_POINTERS]; #endif } AVVkFrameInternal; @@ -1647,6 +1649,7 @@ static void vulkan_free_internal(AVVkFrameInternal *internal) CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i])); if (internal->ext_mem[i]) CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i])); + close(internal->exp_sem[i]); } av_buffer_unref(&internal->cuda_fc_ref); @@ -2724,7 +2727,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, }; CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = { - .type = CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD, + .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */, }; int p_w, p_h; @@ -2763,7 +2766,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, } ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export, - &ext_sem_desc.handle.fd); + &dst_int->exp_sem[i]); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n", vk_ret2str(ret)); @@ -2771,9 +2774,12 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, goto fail; } + ext_sem_desc.handle.fd = dup(dst_int->exp_sem[i]); + ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[i], &ext_sem_desc)); if (ret < 0) { + close(ext_sem_desc.handle.fd); err = AVERROR_EXTERNAL; goto fail; } @@ -2819,6 +2825,11 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, dst_int = dst_f->internal; + for (int i = 0; i < planes; i++) { + s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0; + s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1; + } + ret = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, planes, cuda_dev->stream)); if (ret < 0) { @@ -2857,6 +2868,9 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, goto fail; } + for (int i = 0; i < planes; i++) + dst_f->sem_value[i]++; + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); av_log(hwfc, AV_LOG_VERBOSE, "Transfered CUDA image to Vulkan!\n"); @@ -3638,6 +3652,11 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, dst_int = dst_f->internal; + for (int i = 0; i < planes; i++) { + s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0; + s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1; + } + ret = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, planes, cuda_dev->stream)); if (ret < 0) { @@ -3676,6 +3695,9 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, goto fail; } + for (int i = 0; i < planes; i++) + dst_f->sem_value[i]++; + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); av_log(hwfc, AV_LOG_VERBOSE, "Transfered Vulkan image to CUDA!\n"); From dfc61800a26747dc91bf00b0d841fc88a5d7473d Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 4 Nov 2021 12:33:01 +0100 Subject: [PATCH 113/894] lavfi/vulkan: port to using timeline semaphores --- libavfilter/vulkan.c | 31 +++++++++++++++++++++++++++++++ libavfilter/vulkan.h | 6 ++++++ 2 files changed, 37 insertions(+) diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index e812a3e723..ef890b81d3 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -486,6 +486,13 @@ int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, return AVERROR(ENOMEM); } + e->sem_wait_val = av_fast_realloc(e->sem_wait_val, &e->sem_wait_val_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_val)); + if (!e->sem_wait_val) { + ff_vk_discard_exec_deps(avctx, e); + return AVERROR(ENOMEM); + } + e->sem_sig = av_fast_realloc(e->sem_sig, &e->sem_sig_alloc, (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig)); if (!e->sem_sig) { @@ -493,11 +500,23 @@ int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, return AVERROR(ENOMEM); } + e->sem_sig_val = av_fast_realloc(e->sem_sig_val, &e->sem_sig_val_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val)); + if (!e->sem_sig_val) { + ff_vk_discard_exec_deps(avctx, e); + return AVERROR(ENOMEM); + } + e->sem_wait[e->sem_wait_cnt] = f->sem[i]; e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag; + e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i]; e->sem_wait_cnt++; + /* TODO: fix this in case execution fails */ + f->sem_value[i]++; + e->sem_sig[e->sem_sig_cnt] = f->sem[i]; + e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i]; e->sem_sig_cnt++; } @@ -525,8 +544,18 @@ int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) VulkanFilterContext *s = avctx->priv; FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pWaitSemaphoreValues = e->sem_wait_val, + .pSignalSemaphoreValues = e->sem_sig_val, + .waitSemaphoreValueCount = e->sem_wait_cnt, + .signalSemaphoreValueCount = e->sem_sig_cnt, + }; + VkSubmitInfo s_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, + .commandBufferCount = 1, .pCommandBuffers = &e->bufs[s->cur_queue_idx], @@ -1349,8 +1378,10 @@ static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) av_freep(&e->bufs); av_freep(&e->queues); av_freep(&e->sem_sig); + av_freep(&e->sem_sig_val); av_freep(&e->sem_wait); av_freep(&e->sem_wait_dst); + av_freep(&e->sem_wait_val); av_free(e); } diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index d4a03abfe9..dbe181e898 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -148,12 +148,18 @@ typedef struct FFVkExecContext { int sem_wait_alloc; /* Allocated sem_wait */ int sem_wait_cnt; + uint64_t *sem_wait_val; + int sem_wait_val_alloc; + VkPipelineStageFlagBits *sem_wait_dst; int sem_wait_dst_alloc; /* Allocated sem_wait_dst */ VkSemaphore *sem_sig; int sem_sig_alloc; /* Allocated sem_sig */ int sem_sig_cnt; + + uint64_t *sem_sig_val; + int sem_sig_val_alloc; } FFVkExecContext; typedef struct VulkanFilterContext { From 6bf9a6539e3db94ee88dd2a8e4816fadf10a4970 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 7 Nov 2021 08:16:11 +0100 Subject: [PATCH 114/894] vulkan: add support for encode and decode queues and refactor queue code This simplifies and makes queue family picking simpler and more robust. The requirements on the device context are relaxed. They made no sense in the first place. The video encode/decode extension is still in beta, at least on paper, but I really doubt they'd change needing a separate queue family. --- libavfilter/vf_avgblur_vulkan.c | 3 +- libavfilter/vf_chromaber_vulkan.c | 3 +- libavfilter/vf_overlay_vulkan.c | 3 +- libavfilter/vf_scale_vulkan.c | 3 +- libavfilter/vulkan.h | 11 -- libavutil/hwcontext_vulkan.c | 290 ++++++++++++++++++------------ libavutil/hwcontext_vulkan.h | 40 +++-- 7 files changed, 207 insertions(+), 146 deletions(-) diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 93a7f0d62a..deb2d0f186 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -99,8 +99,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) return AVERROR_EXTERNAL; s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; + s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; { /* Create shader for the horizontal pass */ desc_i[0].updater = s->input_images; diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 9e0926c7c0..89e5ed2167 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -75,8 +75,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) return AVERROR_EXTERNAL; s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; + s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; s->pl = ff_vk_create_pipeline(ctx); if (!s->pl) diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 4b49878b85..1b809f836c 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -89,8 +89,7 @@ static av_cold int init_filter(AVFilterContext *ctx) return AVERROR(ENOMEM); s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; + s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; { /* Create the shader */ const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 2b83170029..3dd6e3ff0b 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -117,8 +117,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) int crop_h = in->height - (in->crop_top + in->crop_bottom); s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; + s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; switch (s->scaler) { case F_NEAREST: diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index dbe181e898..fa77995075 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -49,17 +49,6 @@ goto fail; \ } while (0) -/* Gets the queues count for a single queue family */ -#define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \ - graph ? hwctx->nb_graphics_queues : \ - comp ? (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \ - tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \ - (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \ - 0 \ -) - /* Useful for attaching immutable samplers to arrays */ #define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, } diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ee2e5663b7..91bca22d48 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -17,6 +17,7 @@ */ #define VK_NO_PROTOTYPES +#define VK_ENABLE_BETA_EXTENSIONS #include @@ -25,6 +26,7 @@ #include "avstring.h" #include "imgutils.h" #include "hwcontext.h" +#include "avassert.h" #include "hwcontext_internal.h" #include "hwcontext_vulkan.h" @@ -204,7 +206,7 @@ typedef struct VulkanDevicePriv { VkPhysicalDeviceVulkan12Features device_features_1_2; /* Queues */ - uint32_t qfs[3]; + uint32_t qfs[5]; int num_qfs; /* Debug callback */ @@ -242,16 +244,6 @@ typedef struct AVVkFrameInternal { #endif } AVVkFrameInternal; -#define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \ - graph ? hwctx->nb_graphics_queues : \ - comp ? (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \ - tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \ - (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \ - 0 \ -) - #define DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ VK_IMAGE_USAGE_STORAGE_BIT | \ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \ @@ -903,16 +895,39 @@ end: return err; } -static int search_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) +/* Picks the least used qf with the fewest unneeded flags, or -1 if none found */ +static inline int pick_queue_family(VkQueueFamilyProperties *qf, uint32_t num_qf, + VkQueueFlagBits flags) +{ + int index = -1; + uint32_t min_score = UINT32_MAX; + + for (int i = 0; i < num_qf; i++) { + const VkQueueFlagBits qflags = qf[i].queueFlags; + if (qflags & flags) { + uint32_t score = av_popcount(qflags) + qf[i].timestampValidBits; + if (score < min_score) { + index = i; + min_score = score; + } + } + } + + if (index > -1) + qf[index].timestampValidBits++; + + return index; +} + +static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) { uint32_t num; float *weights; - VkQueueFamilyProperties *qs = NULL; + VkQueueFamilyProperties *qf = NULL; VulkanDevicePriv *p = ctx->internal->priv; VulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - int graph_index = -1, comp_index = -1, tx_index = -1; - VkDeviceQueueCreateInfo *pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos; + int graph_index, comp_index, tx_index, enc_index, dec_index; /* First get the number of queue families */ vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL); @@ -922,81 +937,113 @@ static int search_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) } /* Then allocate memory */ - qs = av_malloc_array(num, sizeof(VkQueueFamilyProperties)); - if (!qs) + qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties)); + if (!qf) return AVERROR(ENOMEM); /* Finally retrieve the queue families */ - vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, qs); + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, qf); -#define SEARCH_FLAGS(expr, out) \ - for (int i = 0; i < num; i++) { \ - const VkQueueFlagBits flags = qs[i].queueFlags; \ - if (expr) { \ - out = i; \ - break; \ + av_log(ctx, AV_LOG_VERBOSE, "Queue families:\n"); + for (int i = 0; i < num; i++) { + av_log(ctx, AV_LOG_VERBOSE, " %i:%s%s%s%s%s%s%s (queues: %i)\n", i, + ((qf[i].queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "", + ((qf[i].queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "", + ((qf[i].queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "", + ((qf[i].queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "", + ((qf[i].queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "", + ((qf[i].queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "", + ((qf[i].queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "", + qf[i].queueCount); + + /* We use this field to keep a score of how many times we've used that + * queue family in order to make better choices. */ + qf[i].timestampValidBits = 0; + } + + /* Pick each queue family to use */ + graph_index = pick_queue_family(qf, num, VK_QUEUE_GRAPHICS_BIT); + comp_index = pick_queue_family(qf, num, VK_QUEUE_COMPUTE_BIT); + tx_index = pick_queue_family(qf, num, VK_QUEUE_TRANSFER_BIT); + enc_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_ENCODE_BIT_KHR); + dec_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_DECODE_BIT_KHR); + + hwctx->queue_family_index = -1; + hwctx->queue_family_comp_index = -1; + hwctx->queue_family_tx_index = -1; + hwctx->queue_family_encode_index = -1; + hwctx->queue_family_decode_index = -1; + +#define SETUP_QUEUE(qf_idx) \ + if (qf_idx > -1) { \ + int fidx = qf_idx; \ + int qc = qf[fidx].queueCount; \ + VkDeviceQueueCreateInfo *pc; \ + \ + if (fidx == graph_index) { \ + hwctx->queue_family_index = fidx; \ + hwctx->nb_graphics_queues = qc; \ + graph_index = -1; \ } \ + if (fidx == comp_index) { \ + hwctx->queue_family_comp_index = fidx; \ + hwctx->nb_comp_queues = qc; \ + comp_index = -1; \ + } \ + if (fidx == tx_index) { \ + hwctx->queue_family_tx_index = fidx; \ + hwctx->nb_tx_queues = qc; \ + tx_index = -1; \ + } \ + if (fidx == enc_index) { \ + hwctx->queue_family_encode_index = fidx; \ + hwctx->nb_encode_queues = qc; \ + enc_index = -1; \ + } \ + if (fidx == dec_index) { \ + hwctx->queue_family_decode_index = fidx; \ + hwctx->nb_decode_queues = qc; \ + dec_index = -1; \ + } \ + \ + pc = av_realloc((void *)cd->pQueueCreateInfos, \ + sizeof(*pc) * (cd->queueCreateInfoCount + 1)); \ + if (!pc) { \ + av_free(qf); \ + return AVERROR(ENOMEM); \ + } \ + cd->pQueueCreateInfos = pc; \ + pc = &pc[cd->queueCreateInfoCount]; \ + \ + weights = av_malloc(qc * sizeof(float)); \ + if (!weights) { \ + av_free(qf); \ + return AVERROR(ENOMEM); \ + } \ + \ + memset(pc, 0, sizeof(*pc)); \ + pc->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; \ + pc->queueFamilyIndex = fidx; \ + pc->queueCount = qc; \ + pc->pQueuePriorities = weights; \ + \ + for (int i = 0; i < qc; i++) \ + weights[i] = 1.0f / qc; \ + \ + cd->queueCreateInfoCount++; \ } - SEARCH_FLAGS(flags & VK_QUEUE_GRAPHICS_BIT, graph_index) - - SEARCH_FLAGS((flags & VK_QUEUE_COMPUTE_BIT) && (i != graph_index), - comp_index) - - SEARCH_FLAGS((flags & VK_QUEUE_TRANSFER_BIT) && (i != graph_index) && - (i != comp_index), tx_index) - -#undef SEARCH_FLAGS -#define ADD_QUEUE(fidx, graph, comp, tx) \ - av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (total queues: %i) for %s%s%s\n", \ - fidx, qs[fidx].queueCount, graph ? "graphics " : "", \ - comp ? "compute " : "", tx ? "transfers " : ""); \ - av_log(ctx, AV_LOG_VERBOSE, " QF %i flags: %s%s%s%s\n", fidx, \ - ((qs[fidx].queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? "(graphics) " : "", \ - ((qs[fidx].queueFlags) & VK_QUEUE_COMPUTE_BIT) ? "(compute) " : "", \ - ((qs[fidx].queueFlags) & VK_QUEUE_TRANSFER_BIT) ? "(transfers) " : "", \ - ((qs[fidx].queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? "(sparse) " : ""); \ - pc[cd->queueCreateInfoCount].queueFamilyIndex = fidx; \ - pc[cd->queueCreateInfoCount].queueCount = qs[fidx].queueCount; \ - weights = av_malloc(qs[fidx].queueCount * sizeof(float)); \ - pc[cd->queueCreateInfoCount].pQueuePriorities = weights; \ - if (!weights) \ - goto fail; \ - for (int i = 0; i < qs[fidx].queueCount; i++) \ - weights[i] = 1.0f; \ - cd->queueCreateInfoCount++; - - ADD_QUEUE(graph_index, 1, comp_index < 0, tx_index < 0 && comp_index < 0) - hwctx->queue_family_index = graph_index; - hwctx->queue_family_comp_index = graph_index; - hwctx->queue_family_tx_index = graph_index; - hwctx->nb_graphics_queues = qs[graph_index].queueCount; - - if (comp_index != -1) { - ADD_QUEUE(comp_index, 0, 1, tx_index < 0) - hwctx->queue_family_tx_index = comp_index; - hwctx->queue_family_comp_index = comp_index; - hwctx->nb_comp_queues = qs[comp_index].queueCount; - } - - if (tx_index != -1) { - ADD_QUEUE(tx_index, 0, 0, 1) - hwctx->queue_family_tx_index = tx_index; - hwctx->nb_tx_queues = qs[tx_index].queueCount; - } + SETUP_QUEUE(graph_index) + SETUP_QUEUE(comp_index) + SETUP_QUEUE(tx_index) + SETUP_QUEUE(enc_index) + SETUP_QUEUE(dec_index) #undef ADD_QUEUE - av_free(qs); + + av_free(qf); return 0; - -fail: - av_freep(&pc[0].pQueuePriorities); - av_freep(&pc[1].pQueuePriorities); - av_freep(&pc[2].pQueuePriorities); - av_free(qs); - - return AVERROR(ENOMEM); } static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, @@ -1271,17 +1318,10 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .pNext = &dev_features_1_1, }; - VkDeviceQueueCreateInfo queue_create_info[3] = { - { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, - { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, - { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, - }; VkDeviceCreateInfo dev_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = &hwctx->device_features, - .pQueueCreateInfos = queue_create_info, - .queueCreateInfoCount = 0, }; hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; @@ -1318,24 +1358,24 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, } p->device_features_1_2.timelineSemaphore = 1; - /* Search queue family */ - if ((err = search_queue_families(ctx, &dev_info))) + /* Setup queue family */ + if ((err = setup_queue_families(ctx, &dev_info))) goto end; if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames, &dev_info.enabledExtensionCount, 0))) { - av_free((void *)queue_create_info[0].pQueuePriorities); - av_free((void *)queue_create_info[1].pQueuePriorities); - av_free((void *)queue_create_info[2].pQueuePriorities); + for (int i = 0; i < dev_info.queueCreateInfoCount; i++) + av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities); + av_free((void *)dev_info.pQueueCreateInfos); goto end; } ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc, &hwctx->act_dev); - av_free((void *)queue_create_info[0].pQueuePriorities); - av_free((void *)queue_create_info[1].pQueuePriorities); - av_free((void *)queue_create_info[2].pQueuePriorities); + for (int i = 0; i < dev_info.queueCreateInfoCount; i++) + av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities); + av_free((void *)dev_info.pQueueCreateInfos); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n", @@ -1366,6 +1406,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; VulkanFunctions *vk = &p->vkfn; + int graph_index, comp_index, tx_index, enc_index, dec_index; /* Set device extension flags */ for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) { @@ -1410,27 +1451,50 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) return AVERROR_EXTERNAL; } -#define CHECK_QUEUE(type, n) \ -if (n >= queue_num) { \ - av_log(ctx, AV_LOG_ERROR, "Invalid %s queue index %i (device has %i queues)!\n", \ - type, n, queue_num); \ - return AVERROR(EINVAL); \ -} + graph_index = hwctx->queue_family_index; + comp_index = hwctx->queue_family_comp_index; + tx_index = hwctx->queue_family_tx_index; + enc_index = hwctx->queue_family_encode_index; + dec_index = hwctx->queue_family_decode_index; - CHECK_QUEUE("graphics", hwctx->queue_family_index) - CHECK_QUEUE("upload", hwctx->queue_family_tx_index) - CHECK_QUEUE("compute", hwctx->queue_family_comp_index) +#define CHECK_QUEUE(type, required, fidx, ctx_qf, qc) \ + do { \ + if (ctx_qf < 0 && required) { \ + av_log(ctx, AV_LOG_ERROR, "%s queue family is required, but marked as missing" \ + " in the context!\n", type); \ + return AVERROR(EINVAL); \ + } else if (fidx < 0 || ctx_qf < 0) { \ + break; \ + } else if (ctx_qf >= queue_num) { \ + av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \ + type, ctx_qf, queue_num); \ + return AVERROR(EINVAL); \ + } \ + \ + av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (queues: %i)" \ + " for%s%s%s%s%s\n", \ + ctx_qf, qc, \ + ctx_qf == graph_index ? " graphics" : "", \ + ctx_qf == comp_index ? " compute" : "", \ + ctx_qf == tx_index ? " transfers" : "", \ + ctx_qf == enc_index ? " encode" : "", \ + ctx_qf == dec_index ? " decode" : ""); \ + graph_index = (ctx_qf == graph_index) ? -1 : graph_index; \ + comp_index = (ctx_qf == comp_index) ? -1 : comp_index; \ + tx_index = (ctx_qf == tx_index) ? -1 : tx_index; \ + enc_index = (ctx_qf == enc_index) ? -1 : enc_index; \ + dec_index = (ctx_qf == dec_index) ? -1 : dec_index; \ + p->qfs[p->num_qfs++] = ctx_qf; \ + } while (0) + + CHECK_QUEUE("graphics", 0, graph_index, hwctx->queue_family_index, hwctx->nb_graphics_queues); + CHECK_QUEUE("upload", 1, tx_index, hwctx->queue_family_tx_index, hwctx->nb_tx_queues); + CHECK_QUEUE("compute", 1, comp_index, hwctx->queue_family_comp_index, hwctx->nb_comp_queues); + CHECK_QUEUE("encode", 0, enc_index, hwctx->queue_family_encode_index, hwctx->nb_encode_queues); + CHECK_QUEUE("decode", 0, dec_index, hwctx->queue_family_decode_index, hwctx->nb_decode_queues); #undef CHECK_QUEUE - p->qfs[p->num_qfs++] = hwctx->queue_family_index; - if ((hwctx->queue_family_tx_index != hwctx->queue_family_index) && - (hwctx->queue_family_tx_index != hwctx->queue_family_comp_index)) - p->qfs[p->num_qfs++] = hwctx->queue_family_tx_index; - if ((hwctx->queue_family_comp_index != hwctx->queue_family_index) && - (hwctx->queue_family_comp_index != hwctx->queue_family_tx_index)) - p->qfs[p->num_qfs++] = hwctx->queue_family_comp_index; - /* Get device capabilities */ vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops); @@ -2076,13 +2140,13 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) err = create_exec_ctx(hwfc, &fp->conv_ctx, dev_hwctx->queue_family_comp_index, - GET_QUEUE_COUNT(dev_hwctx, 0, 1, 0)); + dev_hwctx->nb_comp_queues); if (err) return err; err = create_exec_ctx(hwfc, &fp->upload_ctx, dev_hwctx->queue_family_tx_index, - GET_QUEUE_COUNT(dev_hwctx, 0, 0, 1)); + dev_hwctx->nb_tx_queues); if (err) return err; diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 9ac01e3b46..c83fe3fb1d 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -94,32 +94,44 @@ typedef struct AVVulkanDeviceContext { int nb_enabled_dev_extensions; /** - * Queue family index for graphics - * @note av_hwdevice_create() will set all 3 queue indices if unset - * If there is no dedicated queue for compute or transfer operations, - * they will be set to the graphics queue index which can handle both. - * nb_graphics_queues indicates how many queues were enabled for the - * graphics queue (must be at least 1) + * Queue family index for graphics operations, and the number of queues + * enabled for it. If unavaiable, will be set to -1. Not required. + * av_hwdevice_create() will attempt to find a dedicated queue for each + * queue family, or pick the one with the least unrelated flags set. + * Queue indices here may overlap if a queue has to share capabilities. */ int queue_family_index; int nb_graphics_queues; /** - * Queue family index to use for transfer operations, and the amount of queues - * enabled. In case there is no dedicated transfer queue, nb_tx_queues - * must be 0 and queue_family_tx_index must be the same as either the graphics - * queue or the compute queue, if available. + * Queue family index for transfer operations and the number of queues + * enabled. Required. */ int queue_family_tx_index; int nb_tx_queues; /** - * Queue family index for compute ops, and the amount of queues enabled. - * In case there are no dedicated compute queues, nb_comp_queues must be - * 0 and its queue family index must be set to the graphics queue. + * Queue family index for compute operations and the number of queues + * enabled. Required. */ int queue_family_comp_index; int nb_comp_queues; + + /** + * Queue family index for video encode ops, and the amount of queues enabled. + * If the device doesn't support such, queue_family_encode_index will be -1. + * Not required. + */ + int queue_family_encode_index; + int nb_encode_queues; + + /** + * Queue family index for video decode ops, and the amount of queues enabled. + * If the device doesn't support such, queue_family_decode_index will be -1. + * Not required. + */ + int queue_family_decode_index; + int nb_decode_queues; } AVVulkanDeviceContext; /** @@ -158,7 +170,7 @@ typedef struct AVVulkanFramesContext { * All frames, imported or allocated, will be created with the * VK_IMAGE_CREATE_ALIAS_BIT flag set, so the memory may be aliased if needed. * - * If all three queue family indices in the device context are the same, + * If all queue family indices in the device context are the same, * images will be created with the EXCLUSIVE sharing mode. Otherwise, all images * will be created using the CONCURRENT sharing mode. * From f7f16136388b3f3ef17b0bdacf4e9eb3e7900aca Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 7 Nov 2021 08:18:54 +0100 Subject: [PATCH 115/894] hwcontext_vulkan: report device that's used Not sure why this wasn't done before. --- libavutil/hwcontext_vulkan.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 91bca22d48..6aba9e3b8e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -885,8 +885,13 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) } end: - if (choice > -1) + if (choice > -1) { + av_log(ctx, AV_LOG_VERBOSE, "Device %d selected: %s (%s) (0x%x)\n", + choice, prop[choice].properties.deviceName, + vk_dev_type(prop[choice].properties.deviceType), + prop[choice].properties.deviceID); hwctx->phys_dev = devices[choice]; + } av_free(devices); av_free(prop); From bde1fc5386282142697dbaf91fe57744ba63fec1 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 7 Nov 2021 08:44:46 +0100 Subject: [PATCH 116/894] hwcontext_vulkan: host wait on semaphores before freeing frame --- libavutil/hwcontext_vulkan.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 6aba9e3b8e..69de06e6c2 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -112,6 +112,7 @@ enum VulkanExtensions { /* Semaphores */ \ MACRO(1, 1, EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ MACRO(1, 1, EXT_NO_FLAG, CreateSemaphore) \ + MACRO(1, 1, EXT_NO_FLAG, WaitSemaphores) \ MACRO(1, 1, EXT_NO_FLAG, DestroySemaphore) \ \ /* Memory */ \ @@ -1737,6 +1738,16 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) VulkanFunctions *vk = &p->vkfn; int planes = av_pix_fmt_count_planes(hwfc->sw_format); + VkSemaphoreWaitInfo wait_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .flags = 0x0, + .pSemaphores = f->sem, + .pValues = f->sem_value, + .semaphoreCount = planes, + }; + + vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + vulkan_free_internal(f->internal); for (int i = 0; i < planes; i++) { From 1ffb59c056aec77ffa3c46e30a7f0779fed6daf9 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 7 Nov 2021 09:02:46 +0100 Subject: [PATCH 117/894] hwcontext_vulkan: clean up extensions code and add additional defaults --- libavutil/hwcontext_vulkan.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 69de06e6c2..7281336d73 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -58,8 +58,7 @@ enum VulkanExtensions { EXT_EXTERNAL_FD_MEMORY = 1 << 2, /* VK_KHR_external_memory_fd */ EXT_EXTERNAL_FD_SEM = 1 << 3, /* VK_KHR_external_semaphore_fd */ EXT_EXTERNAL_HOST_MEMORY = 1 << 4, /* VK_EXT_external_memory_host */ - EXT_PUSH_DESCRIPTORS = 1 << 5, /* VK_KHR_push_descriptor */ - EXT_DEBUG_UTILS = 1 << 6, /* VK_EXT_debug_utils */ + EXT_DEBUG_UTILS = 1 << 5, /* VK_EXT_debug_utils */ EXT_NO_FLAG = 1 << 31, }; @@ -457,13 +456,26 @@ static const VulkanOptExtension optional_instance_exts[] = { }; static const VulkanOptExtension optional_device_exts[] = { + /* Misc or required by other extensions */ + { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_EXT_HDR_METADATA_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, EXT_NO_FLAG, }, + + /* Imports/exports */ { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_MEMORY, }, { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, EXT_EXTERNAL_DMABUF_MEMORY, }, { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, EXT_DRM_MODIFIER_FLAGS, }, { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_SEM, }, { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, EXT_EXTERNAL_HOST_MEMORY, }, - { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, EXT_PUSH_DESCRIPTORS, }, - { VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, EXT_NO_FLAG, }, + + /* Video encoding/decoding */ + { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME, EXT_NO_FLAG, }, }; /* Converts return values to strings */ @@ -598,7 +610,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, if (!found) continue; - av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, tstr); + av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); p->extensions |= optional_exts[i].flag; ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); } @@ -613,7 +625,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, } } if (found) { - av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, tstr); + av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); p->extensions |= EXT_DEBUG_UTILS; } else { @@ -1419,8 +1431,6 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) for (int j = 0; j < FF_ARRAY_ELEMS(optional_device_exts); j++) { if (!strcmp(hwctx->enabled_dev_extensions[i], optional_device_exts[j].name)) { - av_log(ctx, AV_LOG_VERBOSE, "Using device extension %s\n", - hwctx->enabled_dev_extensions[i]); p->extensions |= optional_device_exts[j].flag; break; } From d05a18cdc7ea245843a1c785e1e3d7fdf980a130 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 7 Nov 2021 15:57:35 +0100 Subject: [PATCH 118/894] lavu: move hwcontext_vulkan's function loader into separate files This allows for the loader to be shared with libavcodec and libavfilter. --- libavutil/hwcontext_vulkan.c | 293 ++++++++--------------------------- libavutil/vulkan_functions.h | 162 +++++++++++++++++++ libavutil/vulkan_loader.h | 128 +++++++++++++++ 3 files changed, 357 insertions(+), 226 deletions(-) create mode 100644 libavutil/vulkan_functions.h create mode 100644 libavutil/vulkan_loader.h diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 7281336d73..93a304ca95 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -30,6 +30,8 @@ #include "hwcontext_internal.h" #include "hwcontext_vulkan.h" +#include "vulkan_loader.h" + #ifdef _WIN32 #include "compat/w32dlfcn.h" #else @@ -52,126 +54,6 @@ #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) #endif -enum VulkanExtensions { - EXT_EXTERNAL_DMABUF_MEMORY = 1 << 0, /* VK_EXT_external_memory_dma_buf */ - EXT_DRM_MODIFIER_FLAGS = 1 << 1, /* VK_EXT_image_drm_format_modifier */ - EXT_EXTERNAL_FD_MEMORY = 1 << 2, /* VK_KHR_external_memory_fd */ - EXT_EXTERNAL_FD_SEM = 1 << 3, /* VK_KHR_external_semaphore_fd */ - EXT_EXTERNAL_HOST_MEMORY = 1 << 4, /* VK_EXT_external_memory_host */ - EXT_DEBUG_UTILS = 1 << 5, /* VK_EXT_debug_utils */ - - EXT_NO_FLAG = 1 << 31, -}; - -#define FN_LIST(MACRO) \ - /* Instance */ \ - MACRO(0, 0, EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ - MACRO(0, 0, EXT_NO_FLAG, CreateInstance) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyInstance) \ - \ - /* Debug */ \ - MACRO(1, 0, EXT_NO_FLAG, CreateDebugUtilsMessengerEXT) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyDebugUtilsMessengerEXT) \ - \ - /* Device */ \ - MACRO(1, 0, EXT_NO_FLAG, GetDeviceProcAddr) \ - MACRO(1, 0, EXT_NO_FLAG, CreateDevice) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyDevice) \ - \ - MACRO(1, 0, EXT_NO_FLAG, EnumeratePhysicalDevices) \ - MACRO(1, 0, EXT_NO_FLAG, EnumerateDeviceExtensionProperties) \ - \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceMemoryProperties) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFormatProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \ - \ - /* Command pool */ \ - MACRO(1, 1, EXT_NO_FLAG, CreateCommandPool) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyCommandPool) \ - \ - /* Command buffer */ \ - MACRO(1, 1, EXT_NO_FLAG, AllocateCommandBuffers) \ - MACRO(1, 1, EXT_NO_FLAG, BeginCommandBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, EndCommandBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, FreeCommandBuffers) \ - \ - /* Queue */ \ - MACRO(1, 1, EXT_NO_FLAG, GetDeviceQueue) \ - MACRO(1, 1, EXT_NO_FLAG, QueueSubmit) \ - \ - /* Fences */ \ - MACRO(1, 1, EXT_NO_FLAG, CreateFence) \ - MACRO(1, 1, EXT_NO_FLAG, WaitForFences) \ - MACRO(1, 1, EXT_NO_FLAG, ResetFences) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyFence) \ - \ - /* Semaphores */ \ - MACRO(1, 1, EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ - MACRO(1, 1, EXT_NO_FLAG, CreateSemaphore) \ - MACRO(1, 1, EXT_NO_FLAG, WaitSemaphores) \ - MACRO(1, 1, EXT_NO_FLAG, DestroySemaphore) \ - \ - /* Memory */ \ - MACRO(1, 1, EXT_EXTERNAL_FD_MEMORY, GetMemoryFdKHR) \ - MACRO(1, 1, EXT_NO_FLAG, GetMemoryFdPropertiesKHR) \ - MACRO(1, 1, EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT) \ - MACRO(1, 1, EXT_NO_FLAG, AllocateMemory) \ - MACRO(1, 1, EXT_NO_FLAG, MapMemory) \ - MACRO(1, 1, EXT_NO_FLAG, FlushMappedMemoryRanges) \ - MACRO(1, 1, EXT_NO_FLAG, InvalidateMappedMemoryRanges) \ - MACRO(1, 1, EXT_NO_FLAG, UnmapMemory) \ - MACRO(1, 1, EXT_NO_FLAG, FreeMemory) \ - \ - /* Commands */ \ - MACRO(1, 1, EXT_NO_FLAG, CmdPipelineBarrier) \ - MACRO(1, 1, EXT_NO_FLAG, CmdCopyBufferToImage) \ - MACRO(1, 1, EXT_NO_FLAG, CmdCopyImageToBuffer) \ - \ - /* Buffer */ \ - MACRO(1, 1, EXT_NO_FLAG, GetBufferMemoryRequirements2) \ - MACRO(1, 1, EXT_NO_FLAG, CreateBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, BindBufferMemory) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyBuffer) \ - \ - /* Image */ \ - MACRO(1, 1, EXT_DRM_MODIFIER_FLAGS, GetImageDrmFormatModifierPropertiesEXT) \ - MACRO(1, 1, EXT_NO_FLAG, GetImageMemoryRequirements2) \ - MACRO(1, 1, EXT_NO_FLAG, CreateImage) \ - MACRO(1, 1, EXT_NO_FLAG, BindImageMemory2) \ - MACRO(1, 1, EXT_NO_FLAG, GetImageSubresourceLayout) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyImage) - -#define PFN_DEF(req_inst, req_dev, ext_flag, name) \ - PFN_vk##name name; - -typedef struct VulkanFunctions { - FN_LIST(PFN_DEF) -} VulkanFunctions; - -#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \ - { \ - req_inst, \ - req_dev, \ - offsetof(VulkanFunctions, name), \ - ext_flag, \ - { "vk"#name, "vk"#name"EXT", "vk"#name"KHR" } \ - }, - -typedef struct VulkanFunctionsLoadInfo { - int req_inst; - int req_dev; - size_t struct_offset; - enum VulkanExtensions ext_flag; - const char *names[3]; -} VulkanFunctionsLoadInfo; - -static const VulkanFunctionsLoadInfo vk_load_info[] = { - FN_LIST(PFN_LOAD_INFO) -}; - typedef struct VulkanQueueCtx { VkFence fence; VkQueue queue; @@ -194,7 +76,7 @@ typedef struct VulkanExecCtx { typedef struct VulkanDevicePriv { /* Vulkan library and loader functions */ void *libvulkan; - VulkanFunctions vkfn; + FFVulkanFunctions vkfn; /* Properties */ VkPhysicalDeviceProperties2 props; @@ -213,7 +95,7 @@ typedef struct VulkanDevicePriv { VkDebugUtilsMessengerEXT debug_ctx; /* Extensions */ - enum VulkanExtensions extensions; + FFVulkanExtensions extensions; /* Settings */ int use_linear_images; @@ -349,7 +231,7 @@ static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, { AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *priv = dev_ctx->internal->priv; - VulkanFunctions *vk = &priv->vkfn; + FFVulkanFunctions *vk = &priv->vkfn; const VkFormat *fmt = av_vkfmt_from_pixfmt(p); int planes = av_pix_fmt_count_planes(p); @@ -405,50 +287,9 @@ static int load_libvulkan(AVHWDeviceContext *ctx) return 0; } -static int load_functions(AVHWDeviceContext *ctx, int has_inst, int has_dev) -{ - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; - - for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) { - const VulkanFunctionsLoadInfo *load = &vk_load_info[i]; - PFN_vkVoidFunction fn; - - if (load->req_dev && !has_dev) - continue; - if (load->req_inst && !has_inst) - continue; - - for (int j = 0; j < FF_ARRAY_ELEMS(load->names); j++) { - const char *name = load->names[j]; - - if (load->req_dev) - fn = vk->GetDeviceProcAddr(hwctx->act_dev, name); - else if (load->req_inst) - fn = hwctx->get_proc_addr(hwctx->inst, name); - else - fn = hwctx->get_proc_addr(NULL, name); - - if (fn) - break; - } - - if (!fn && ((p->extensions &~ EXT_NO_FLAG) & load->ext_flag)) { - av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated" - "as supported, but got NULL function pointer!\n", load->names[0]); - return AVERROR_EXTERNAL; - } - - *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn; - } - - return 0; -} - typedef struct VulkanOptExtension { const char *name; - enum VulkanExtensions flag; + FFVulkanExtensions flag; } VulkanOptExtension; static const VulkanOptExtension optional_instance_exts[] = { @@ -457,25 +298,25 @@ static const VulkanOptExtension optional_instance_exts[] = { static const VulkanOptExtension optional_device_exts[] = { /* Misc or required by other extensions */ - { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_HDR_METADATA_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_HDR_METADATA_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, /* Imports/exports */ - { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_MEMORY, }, - { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, EXT_EXTERNAL_DMABUF_MEMORY, }, - { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, EXT_DRM_MODIFIER_FLAGS, }, - { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_SEM, }, - { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, EXT_EXTERNAL_HOST_MEMORY, }, + { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, + { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY }, + { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS }, + { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, + { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, /* Video encoding/decoding */ - { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, }; /* Converts return values to strings */ @@ -548,7 +389,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *tstr; const char **extension_names = NULL; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int err = 0, found, extensions_found = 0; @@ -627,7 +468,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, if (found) { av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); - p->extensions |= EXT_DEBUG_UTILS; + p->extensions |= FF_VK_EXT_DEBUG_UTILS; } else { av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n", tstr); @@ -680,7 +521,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) int err = 0; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); const int debug_mode = debug_opt && strtol(debug_opt->value, NULL, 10); @@ -703,7 +544,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return err; } - err = load_functions(ctx, 0, 0); + err = ff_vk_load_functions(ctx, vk, p->extensions, 0, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n"); return err; @@ -734,7 +575,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return AVERROR_EXTERNAL; } - err = load_functions(ctx, 1, 0); + err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n"); return err; @@ -791,7 +632,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) uint32_t num; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkPhysicalDevice *devices = NULL; VkPhysicalDeviceIDProperties *idp = NULL; VkPhysicalDeviceProperties2 *prop = NULL; @@ -943,7 +784,7 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) float *weights; VkQueueFamilyProperties *qf = NULL; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int graph_index, comp_index, tx_index, enc_index, dec_index; @@ -1070,7 +911,7 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VkResult ret; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkCommandPoolCreateInfo cqueue_create = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -1126,7 +967,7 @@ static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) { AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; if (cmd->queues) { for (int i = 0; i < cmd->nb_queues; i++) { @@ -1179,7 +1020,7 @@ static int wait_start_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkCommandBufferBeginInfo cmd_start = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -1252,7 +1093,7 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VkResult ret; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; ret = vk->EndCommandBuffer(cmd->bufs[cmd->cur_queue_idx]); if (ret != VK_SUCCESS) { @@ -1292,7 +1133,7 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, static void vulkan_device_free(AVHWDeviceContext *ctx) { VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; vk->DestroyDevice(hwctx->act_dev, hwctx->alloc); @@ -1323,7 +1164,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkResult ret; AVDictionaryEntry *opt_d; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; VkPhysicalDeviceVulkan12Features dev_features_1_2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, @@ -1423,7 +1264,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) uint32_t queue_num; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int graph_index, comp_index, tx_index, enc_index, dec_index; /* Set device extension flags */ @@ -1437,7 +1278,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) } } - err = load_functions(ctx, 1, 1); + err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 1); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n"); return err; @@ -1455,7 +1296,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->props.properties.limits.optimalBufferCopyRowPitchAlignment); av_log(ctx, AV_LOG_VERBOSE, " minMemoryMapAlignment: %"SIZE_SPECIFIER"\n", p->props.properties.limits.minMemoryMapAlignment); - if (p->extensions & EXT_EXTERNAL_HOST_MEMORY) + if (p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %"PRIu64"\n", p->hprops.minImportedHostPointerAlignment); @@ -1657,7 +1498,7 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkResult ret; int index = -1; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *dev_hwctx = ctx->hwctx; VkMemoryAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, @@ -1745,7 +1586,7 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) AVHWFramesContext *hwfc = opaque; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkSemaphoreWaitInfo wait_info = { @@ -1776,7 +1617,7 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; @@ -1853,7 +1694,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VkAccessFlags new_access; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; @@ -1956,7 +1797,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; enum AVPixelFormat format = hwfc->sw_format; const VkFormat *img_fmts = av_vkfmt_from_pixfmt(format); @@ -1969,7 +1810,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkSemaphoreTypeCreateInfo sem_type_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, - .pNext = p->extensions & EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, + .pNext = p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, .initialValue = 0, }; @@ -2053,7 +1894,7 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanFramesContext *hwctx = hwfc->hwctx; AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -2100,11 +1941,11 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) .pNext = hwctx->create_pnext, }; - if (p->extensions & EXT_EXTERNAL_FD_MEMORY) + if (p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); @@ -2242,7 +2083,7 @@ static void vulkan_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; /* Check if buffer needs flushing */ if ((map->flags & AV_HWFRAME_MAP_WRITE) && @@ -2279,7 +2120,7 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanMapping *map = av_mallocz(sizeof(VulkanMapping)); if (!map) @@ -2369,7 +2210,7 @@ static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; for (int i = 0; i < planes; i++) { vk->DestroyImage(hwctx->act_dev, map->frame->img[i], hwctx->alloc); @@ -2414,7 +2255,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f AVHWDeviceContext *ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; @@ -2763,7 +2604,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data; AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; @@ -2985,13 +2826,13 @@ static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, #if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_vaapi(hwfc, dst, src, flags); else return AVERROR(ENOSYS); #endif case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_drm(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3032,7 +2873,7 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, VkResult ret; AVVkFrame *f = (AVVkFrame *)src->data[0]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); @@ -3156,13 +2997,13 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_LIBDRM case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_drm(hwfc, dst, src, flags); else return AVERROR(ENOSYS); #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_vaapi(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3185,7 +3026,7 @@ static void free_buf(void *opaque, uint8_t *data) AVHWDeviceContext *ctx = opaque; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; ImageBuffer *vkbuf = (ImageBuffer *)data; if (vkbuf->buf) @@ -3215,7 +3056,7 @@ static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, int use_ded_mem; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkBufferCreateInfo buf_spawn = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -3302,7 +3143,7 @@ static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[ VkResult ret; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkMappedMemoryRange invalidate_ctx[AV_NUM_DATA_POINTERS]; int invalidate_count = 0; @@ -3361,7 +3202,7 @@ static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, VkResult ret; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkMappedMemoryRange flush_ctx[AV_NUM_DATA_POINTERS]; int flush_count = 0; @@ -3410,7 +3251,7 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, AVVkFrame *frame = (AVVkFrame *)f->data[0]; VulkanFramesPriv *fp = hwfc->internal->priv; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int bar_num = 0; VkPipelineStageFlagBits sem_wait_dst[AV_NUM_DATA_POINTERS]; @@ -3540,7 +3381,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, AVHWDeviceContext *dev_ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVFrame tmp; AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; @@ -3550,7 +3391,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, const int planes = av_pix_fmt_count_planes(swf->format); int host_mapped[AV_NUM_DATA_POINTERS] = { 0 }; - const int map_host = !!(p->extensions & EXT_EXTERNAL_HOST_MEMORY); + const int map_host = !!(p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY); if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) { av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n"); @@ -3696,8 +3537,8 @@ static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, switch (src->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: - if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && - (p->extensions & EXT_EXTERNAL_FD_SEM)) + if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) return vulkan_transfer_data_from_cuda(hwfc, dst, src); #endif default: @@ -3811,8 +3652,8 @@ static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: - if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && - (p->extensions & EXT_EXTERNAL_FD_SEM)) + if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) return vulkan_transfer_data_to_cuda(hwfc, dst, src); #endif default: diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h new file mode 100644 index 0000000000..de2054e0c2 --- /dev/null +++ b/libavutil/vulkan_functions.h @@ -0,0 +1,162 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_VULKAN_FUNCTIONS_H +#define AVUTIL_VULKAN_FUNCTIONS_H + +/* An enum of bitflags for every optional extension we need */ +typedef enum FFVulkanExtensions { + FF_VK_EXT_EXTERNAL_DMABUF_MEMORY = 1ULL << 0, /* VK_EXT_external_memory_dma_buf */ + FF_VK_EXT_DRM_MODIFIER_FLAGS = 1ULL << 1, /* VK_EXT_image_drm_format_modifier */ + FF_VK_EXT_EXTERNAL_FD_MEMORY = 1ULL << 2, /* VK_KHR_external_memory_fd */ + FF_VK_EXT_EXTERNAL_FD_SEM = 1ULL << 3, /* VK_KHR_external_semaphore_fd */ + FF_VK_EXT_EXTERNAL_HOST_MEMORY = 1ULL << 4, /* VK_EXT_external_memory_host */ + FF_VK_EXT_DEBUG_UTILS = 1ULL << 5, /* VK_EXT_debug_utils */ + + FF_VK_EXT_NO_FLAG = 1ULL << 63, +} FFVulkanExtensions; + +/* Macro containing every function that we utilize in our codebase */ +#define FN_LIST(MACRO) \ + /* Instance */ \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, CreateInstance) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyInstance) \ + \ + /* Debug */ \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDebugUtilsMessengerEXT) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDebugUtilsMessengerEXT) \ + \ + /* Device */ \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetDeviceProcAddr) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDevice) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDevice) \ + \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumeratePhysicalDevices) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumerateDeviceExtensionProperties) \ + \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceMemoryProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFormatProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \ + \ + /* Command pool */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateCommandPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyCommandPool) \ + \ + /* Command buffer */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateCommandBuffers) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BeginCommandBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, EndCommandBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeCommandBuffers) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdDispatch) \ + \ + /* Queue */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetDeviceQueue) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, QueueSubmit) \ + \ + /* Fences */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateFence) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, WaitForFences) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, ResetFences) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyFence) \ + \ + /* Semaphores */ \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSemaphore) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, WaitSemaphores) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySemaphore) \ + \ + /* Memory */ \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_MEMORY, GetMemoryFdKHR) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetMemoryFdPropertiesKHR) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, MapMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FlushMappedMemoryRanges) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, InvalidateMappedMemoryRanges) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, UnmapMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeMemory) \ + \ + /* Commands */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBindDescriptorSets) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPushConstants) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBindPipeline) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdCopyBufferToImage) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdCopyImageToBuffer) \ + \ + /* Buffer */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetBufferMemoryRequirements2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BindBufferMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyBuffer) \ + \ + /* Image */ \ + MACRO(1, 1, FF_VK_EXT_DRM_MODIFIER_FLAGS, GetImageDrmFormatModifierPropertiesEXT) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetImageMemoryRequirements2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateImage) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BindImageMemory2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetImageSubresourceLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyImage) \ + \ + /* ImageView */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateImageView) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyImageView) \ + \ + /* DescriptorSet */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorSetLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateDescriptorSets) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorSetLayout) \ + \ + /* DescriptorUpdateTemplate */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, UpdateDescriptorSetWithTemplate) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorUpdateTemplate) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorUpdateTemplate) \ + \ + /* Pipeline */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreatePipelineLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipelineLayout) \ + \ + /* PipelineLayout */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateComputePipelines) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipeline) \ + \ + /* Sampler */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSampler) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySampler) \ + \ + /* Shaders */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateShaderModule) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyShaderModule) + +/* Macro to turn a function name into a definition */ +#define PFN_DEF(req_inst, req_dev, ext_flag, name) \ + PFN_vk##name name; + +/* Structure with the definition of all listed functions */ +typedef struct FFVulkanFunctions { + FN_LIST(PFN_DEF) +} FFVulkanFunctions; + +#endif /* AVUTIL_VULKAN_FUNCTIONS_H */ diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h new file mode 100644 index 0000000000..838d26d271 --- /dev/null +++ b/libavutil/vulkan_loader.h @@ -0,0 +1,128 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_VULKAN_LOADER_H +#define AVUTIL_VULKAN_LOADER_H + +#include "vulkan_functions.h" + +/* Macro to turn a function name into a loader struct */ +#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \ + { \ + req_inst, \ + req_dev, \ + offsetof(FFVulkanFunctions, name), \ + ext_flag, \ + { "vk"#name, "vk"#name"EXT", "vk"#name"KHR" } \ + }, + +static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, + int nb_extensions) +{ + static const struct ExtensionMap { + const char *name; + FFVulkanExtensions flag; + } extension_map[] = { + { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY }, + { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS }, + { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, + { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, + { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS } + }; + + FFVulkanExtensions mask = 0x0; + + for (int i = 0; i < nb_extensions; i++) { + for (int j = 0; j < FF_ARRAY_ELEMS(extension_map); j++) { + if (!strcmp(extensions[i], extension_map[j].name)) { + mask |= extension_map[j].flag; + continue; + } + } + } + + return mask; +} + +/** + * Function loader. + * Vulkan function from scratch loading happens in 3 stages - the first one + * is before any initialization has happened, and you have neither an instance + * structure nor a device structure. At this stage, you can only get the bare + * minimals to initialize an instance. + * The second stage is when you have an instance. At this stage, you can + * initialize a VkDevice, and have an idea of what extensions each device + * supports. + * Finally, in the third stage, you can proceed and load all core functions, + * plus you can be sure that any extensions you've enabled during device + * initialization will be available. + */ +static inline int ff_vk_load_functions(AVHWDeviceContext *ctx, + FFVulkanFunctions *vk, + uint64_t extensions_mask, + int has_inst, int has_dev) +{ + AVVulkanDeviceContext *hwctx = ctx->hwctx; + + static const struct FunctionLoadInfo { + int req_inst; + int req_dev; + size_t struct_offset; + FFVulkanExtensions ext_flag; + const char *names[3]; + } vk_load_info[] = { + FN_LIST(PFN_LOAD_INFO) + }; + + for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) { + const struct FunctionLoadInfo *load = &vk_load_info[i]; + PFN_vkVoidFunction fn; + + if (load->req_dev && !has_dev) + continue; + if (load->req_inst && !has_inst) + continue; + + for (int j = 0; j < FF_ARRAY_ELEMS(load->names); j++) { + const char *name = load->names[j]; + + if (load->req_dev) + fn = vk->GetDeviceProcAddr(hwctx->act_dev, name); + else if (load->req_inst) + fn = hwctx->get_proc_addr(hwctx->inst, name); + else + fn = hwctx->get_proc_addr(NULL, name); + + if (fn) + break; + } + + if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) { + av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated" + "as supported, but got NULL function pointer!\n", load->names[0]); + return AVERROR_EXTERNAL; + } + + *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn; + } + + return 0; +} + +#endif /* AVUTIL_VULKAN_LOADER_H */ From fef85c376adabc15715ed8d9c53cc8e889c9c7dc Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 7 Nov 2021 15:58:31 +0100 Subject: [PATCH 119/894] lavfi/vulkan: use libavutil's vulkan loader This finally fully eliminates the need to statically link to libvulkan! --- configure | 10 +- libavfilter/vf_avgblur_vulkan.c | 13 ++- libavfilter/vf_chromaber_vulkan.c | 13 ++- libavfilter/vf_overlay_vulkan.c | 13 ++- libavfilter/vf_scale_vulkan.c | 13 ++- libavfilter/vulkan.c | 186 ++++++++++++++++++------------ libavfilter/vulkan.h | 5 + 7 files changed, 148 insertions(+), 105 deletions(-) diff --git a/configure b/configure index 103829e688..804bbe4c53 100755 --- a/configure +++ b/configure @@ -3564,7 +3564,7 @@ ass_filter_deps="libass" atempo_filter_deps="avcodec" atempo_filter_select="rdft" avgblur_opencl_filter_deps="opencl" -avgblur_vulkan_filter_deps="vulkan_lib libglslang" +avgblur_vulkan_filter_deps="libglslang" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" bm3d_filter_deps="avcodec" @@ -3572,7 +3572,7 @@ bm3d_filter_select="dct" boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" -chromaber_vulkan_filter_deps="vulkan_lib libglslang" +chromaber_vulkan_filter_deps="libglslang" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" convolution_opencl_filter_deps="opencl" @@ -3635,7 +3635,7 @@ openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" -overlay_vulkan_filter_deps="vulkan_lib libglslang" +overlay_vulkan_filter_deps="libglslang" owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" @@ -3698,7 +3698,7 @@ zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" -scale_vulkan_filter_deps="vulkan_lib libglslang" +scale_vulkan_filter_deps="libglslang" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" xfade_opencl_filter_deps="opencl" @@ -6826,8 +6826,6 @@ enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if. if enabled vulkan; then require_pkg_config_cpp vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || require_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_2" - # vulkan_lib should be removed once glslang filters are updated - check_pkg_config vulkan_lib "vulkan >= 1.2.189" "vulkan/vulkan.h" vkCreateInstance fi if enabled x86; then diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index deb2d0f186..158ccf02df 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -203,6 +203,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f int err; VkCommandBuffer cmd_buf; AvgBlurVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkctx.vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; @@ -279,9 +280,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f }, }; - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); in->layout[i] = bar[0].newLayout; in->access[i] = bar[0].dstAccessMask; @@ -295,13 +296,13 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor); - vkCmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, s->vkctx.output_height, 1); ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver); - vkCmdDispatch(cmd_buf, s->vkctx.output_width, - FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); + vk->CmdDispatch(cmd_buf, s->vkctx.output_width, + FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 89e5ed2167..2503972c2a 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -173,6 +173,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) int err = 0; VkCommandBuffer cmd_buf; ChromaticAberrationVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkctx.vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); @@ -228,9 +229,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) }, }; - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); in->layout[i] = bar[0].newLayout; in->access[i] = bar[0].dstAccessMask; @@ -244,9 +245,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) ff_vk_update_push_exec(avctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(s->opts), &s->opts); - vkCmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + vk->CmdDispatch(cmd_buf, + FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 1b809f836c..77b3668819 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -231,6 +231,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, int err; VkCommandBuffer cmd_buf; OverlayVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkctx.vkfn; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); AVVkFrame *out = (AVVkFrame *)out_f->data[0]; @@ -310,9 +311,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, }, }; - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); main->layout[i] = bar[0].newLayout; main->access[i] = bar[0].dstAccessMask; @@ -326,9 +327,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); - vkCmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + vk->CmdDispatch(cmd_buf, + FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); ff_vk_add_exec_dep(avctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); ff_vk_add_exec_dep(avctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 3dd6e3ff0b..83e101954b 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -295,6 +295,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) int err = 0; VkCommandBuffer cmd_buf; ScaleVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkctx.vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2]; @@ -366,15 +367,15 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) out->access[i] = bar.dstAccessMask; } - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, barrier_count, barriers); + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, barrier_count, barriers); ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); - vkCmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + vk->CmdDispatch(cmd_buf, + FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index ef890b81d3..4ac8e5e90a 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -20,6 +20,8 @@ #include "vulkan.h" #include "glslang.h" +#include "libavutil/vulkan_loader.h" + /* Generic macro for creating contexts which need to keep their addresses * if another context is created. */ #define FN_CREATING(ctx, type, shortname, array, num) \ @@ -95,14 +97,15 @@ static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, VkPhysicalDeviceProperties props; VkPhysicalDeviceMemoryProperties mprops; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkMemoryAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = alloc_extension, }; - vkGetPhysicalDeviceProperties(s->hwctx->phys_dev, &props); - vkGetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &mprops); + vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &props); + vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &mprops); /* Align if we need to */ if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) @@ -134,8 +137,8 @@ static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, alloc_info.memoryTypeIndex = index; - ret = vkAllocateMemory(s->hwctx->act_dev, &alloc_info, - s->hwctx->alloc, mem); + ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info, + s->hwctx->alloc, mem); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n", ff_vk_ret2str(ret)); @@ -154,6 +157,7 @@ int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, VkResult ret; int use_ded_mem; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkBufferCreateInfo buf_spawn = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -179,7 +183,7 @@ int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, .pNext = &ded_req, }; - ret = vkCreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); + ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to create buffer: %s\n", ff_vk_ret2str(ret)); @@ -188,7 +192,7 @@ int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, req_desc.buffer = buf->buf; - vkGetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req); + vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req); /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | @@ -202,7 +206,7 @@ int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, if (err) return err; - ret = vkBindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0); + ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", ff_vk_ret2str(ret)); @@ -217,12 +221,13 @@ int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], { VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkMappedMemoryRange *inval_list = NULL; int inval_count = 0; for (int i = 0; i < nb_buffers; i++) { - ret = vkMapMemory(s->hwctx->act_dev, buf[i].mem, 0, - VK_WHOLE_SIZE, 0, (void **)&mem[i]); + ret = vk->MapMemory(s->hwctx->act_dev, buf[i].mem, 0, + VK_WHOLE_SIZE, 0, (void **)&mem[i]); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", ff_vk_ret2str(ret)); @@ -249,8 +254,8 @@ int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], } if (inval_count) { - ret = vkInvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count, - inval_list); + ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count, + inval_list); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", ff_vk_ret2str(ret)); @@ -267,6 +272,7 @@ int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, int err = 0; VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkMappedMemoryRange *flush_list = NULL; int flush_count = 0; @@ -288,8 +294,8 @@ int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, } if (flush_count) { - ret = vkFlushMappedMemoryRanges(s->hwctx->act_dev, flush_count, - flush_list); + ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count, + flush_list); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n", ff_vk_ret2str(ret)); @@ -298,7 +304,7 @@ int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, } for (int i = 0; i < nb_buffers; i++) - vkUnmapMemory(s->hwctx->act_dev, buf[i].mem); + vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem); return err; } @@ -306,13 +312,15 @@ int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf) { VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; + if (!buf) return; if (buf->buf != VK_NULL_HANDLE) - vkDestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); + vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); if (buf->mem != VK_NULL_HANDLE) - vkFreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); + vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); } int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl, @@ -341,6 +349,7 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) VkResult ret; FFVkExecContext *e; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; int queue_family = s->queue_family_idx; int nb_queues = s->queue_count; @@ -369,7 +378,7 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) return AVERROR(ENOMEM); /* Create command pool */ - ret = vkCreateCommandPool(s->hwctx->act_dev, &cqueue_create, + ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create, s->hwctx->alloc, &e->pool); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Command pool creation failure: %s\n", @@ -380,7 +389,7 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) cbuf_create.commandPool = e->pool; /* Allocate command buffer */ - ret = vkAllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs); + ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", ff_vk_ret2str(ret)); @@ -389,7 +398,7 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) for (int i = 0; i < nb_queues; i++) { FFVkQueueCtx *q = &e->queues[i]; - vkGetDeviceQueue(s->hwctx->act_dev, queue_family, i, &q->queue); + vk->GetDeviceQueue(s->hwctx->act_dev, queue_family, i, &q->queue); } *ctx = e; @@ -418,6 +427,7 @@ int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) { VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; VkCommandBufferBeginInfo cmd_start = { @@ -430,22 +440,22 @@ int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) VkFenceCreateInfo fence_spawn = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, }; - ret = vkCreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc, - &q->fence); + ret = vk->CreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc, + &q->fence); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } } else { - vkWaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vkResetFences(s->hwctx->act_dev, 1, &q->fence); + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); } /* Discard queue dependencies */ ff_vk_discard_exec_deps(avctx, e); - ret = vkBeginCommandBuffer(e->bufs[s->cur_queue_idx], &cmd_start); + ret = vk->BeginCommandBuffer(e->bufs[s->cur_queue_idx], &cmd_start); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to start command recoding: %s\n", ff_vk_ret2str(ret)); @@ -542,6 +552,7 @@ int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) { VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { @@ -567,14 +578,14 @@ int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) .signalSemaphoreCount = e->sem_sig_cnt, }; - ret = vkEndCommandBuffer(e->bufs[s->cur_queue_idx]); + ret = vk->EndCommandBuffer(e->bufs[s->cur_queue_idx]); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } - ret = vkQueueSubmit(q->queue, 1, &s_info, q->fence); + ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", ff_vk_ret2str(ret)); @@ -666,7 +677,7 @@ int ff_vk_filter_config_input(AVFilterLink *inlink) if (avctx->inputs[0] != inlink) return 0; - input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; + input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data; if (input_frames->format != AV_PIX_FMT_VULKAN) return AVERROR(EINVAL); @@ -677,6 +688,13 @@ int ff_vk_filter_config_input(AVFilterLink *inlink) if (err < 0) return err; + s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions, + s->hwctx->nb_enabled_dev_extensions); + + err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1); + if (err < 0) + return err; + /* Default output parameters match input parameters. */ s->input_format = input_frames->sw_format; if (s->output_format == AV_PIX_FMT_NONE) @@ -788,6 +806,7 @@ VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, { VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkSamplerCreateInfo sampler_info = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, @@ -808,8 +827,8 @@ VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, if (!sampler) return NULL; - ret = vkCreateSampler(s->hwctx->act_dev, &sampler_info, - s->hwctx->alloc, sampler); + ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info, + s->hwctx->alloc, sampler); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init sampler: %s\n", ff_vk_ret2str(ret)); @@ -845,8 +864,10 @@ typedef struct ImageViewCtx { static void destroy_imageview(void *opaque, uint8_t *data) { VulkanFilterContext *s = opaque; + FFVulkanFunctions *vk = &s->vkfn; ImageViewCtx *iv = (ImageViewCtx *)data; - vkDestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc); + + vk->DestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc); av_free(iv); } @@ -857,6 +878,8 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, int err; AVBufferRef *buf; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; + VkImageViewCreateInfo imgview_spawn = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = NULL, @@ -875,8 +898,8 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, ImageViewCtx *iv = av_mallocz(sizeof(*iv)); - VkResult ret = vkCreateImageView(s->hwctx->act_dev, &imgview_spawn, - s->hwctx->alloc, &iv->view); + VkResult ret = vk->CreateImageView(s->hwctx->act_dev, &imgview_spawn, + s->hwctx->alloc, &iv->view); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to create imageview: %s\n", ff_vk_ret2str(ret)); @@ -961,6 +984,7 @@ int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, { VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkShaderModuleCreateInfo shader_create; GLSlangResult *res; @@ -994,8 +1018,8 @@ int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, shader_create.flags = 0; shader_create.pCode = res->data; - ret = vkCreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, - &shd->shader.module); + ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, + &shd->shader.module); /* Free the GLSlangResult struct */ av_free(res->data); @@ -1041,6 +1065,7 @@ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, VkResult ret; VkDescriptorSetLayout *layout; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; if (only_print_to_shader) goto print; @@ -1073,8 +1098,8 @@ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, desc_create_layout.pBindings = desc_binding; desc_create_layout.bindingCount = num; - ret = vkCreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, - s->hwctx->alloc, layout); + ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, + s->hwctx->alloc, layout); av_free(desc_binding); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " @@ -1178,11 +1203,12 @@ void ff_vk_update_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, int set_id) { VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; - vkUpdateDescriptorSetWithTemplate(s->hwctx->act_dev, - pl->desc_set[s->cur_queue_idx * pl->desc_layout_num + set_id], - pl->desc_template[set_id], - s); + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, + pl->desc_set[set_id], + pl->desc_template[set_id], + s); } void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, @@ -1190,14 +1216,17 @@ void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, size_t size, void *src) { VulkanFilterContext *s = avctx->priv; - vkCmdPushConstants(e->bufs[s->cur_queue_idx], e->bound_pl->pipeline_layout, - stage, offset, size, src); + FFVulkanFunctions *vk = &s->vkfn; + + vk->CmdPushConstants(e->bufs[s->cur_queue_idx], e->bound_pl->pipeline_layout, + stage, offset, size, src); } int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) { VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; pl->descriptor_sets_num = pl->desc_layout_num * s->queue_count; @@ -1209,8 +1238,8 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) .maxSets = pl->descriptor_sets_num, }; - ret = vkCreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, - s->hwctx->alloc, &pl->desc_pool); + ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, + s->hwctx->alloc, &pl->desc_pool); av_freep(&pl->pool_size_desc); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " @@ -1231,8 +1260,8 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) if (!pl->desc_set) return AVERROR(ENOMEM); - ret = vkAllocateDescriptorSets(s->hwctx->act_dev, &alloc_info, - pl->desc_set); + ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &alloc_info, + pl->desc_set); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n", ff_vk_ret2str(ret)); @@ -1249,8 +1278,8 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) .pPushConstantRanges = pl->push_consts, }; - ret = vkCreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, - s->hwctx->alloc, &pl->pipeline_layout); + ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, + s->hwctx->alloc, &pl->pipeline_layout); av_freep(&pl->push_consts); pl->push_consts_num = 0; if (ret != VK_SUCCESS) { @@ -1271,10 +1300,10 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) for (int i = 0; i < pl->descriptor_sets_num; i++) { desc_template_info = &pl->desc_template_info[i % pl->desc_layout_num]; desc_template_info->pipelineLayout = pl->pipeline_layout; - ret = vkCreateDescriptorUpdateTemplate(s->hwctx->act_dev, - desc_template_info, - s->hwctx->alloc, - &pl->desc_template[i]); + ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev, + desc_template_info, + s->hwctx->alloc, + &pl->desc_template[i]); av_free((void *)desc_template_info->pDescriptorUpdateEntries); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor " @@ -1300,6 +1329,7 @@ int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl) int i; VkResult ret; VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; VkComputePipelineCreateInfo pipe = { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, @@ -1317,8 +1347,8 @@ int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl) return AVERROR(EINVAL); } - ret = vkCreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe, - s->hwctx->alloc, &pl->pipeline); + ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe, + s->hwctx->alloc, &pl->pipeline); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n", ff_vk_ret2str(ret)); @@ -1334,30 +1364,33 @@ void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, VulkanPipeline *pl) { VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; - vkCmdBindPipeline(e->bufs[s->cur_queue_idx], pl->bind_point, pl->pipeline); + vk->CmdBindPipeline(e->bufs[s->cur_queue_idx], pl->bind_point, pl->pipeline); - vkCmdBindDescriptorSets(e->bufs[s->cur_queue_idx], pl->bind_point, - pl->pipeline_layout, 0, pl->descriptor_sets_num, - pl->desc_set, 0, 0); + vk->CmdBindDescriptorSets(e->bufs[s->cur_queue_idx], pl->bind_point, + pl->pipeline_layout, 0, pl->descriptor_sets_num, + pl->desc_set, 0, 0); e->bound_pl = pl; } static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) { + FFVulkanFunctions *vk = &s->vkfn; + /* Make sure all queues have finished executing */ for (int i = 0; i < s->queue_count; i++) { FFVkQueueCtx *q = &e->queues[i]; if (q->fence) { - vkWaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vkResetFences(s->hwctx->act_dev, 1, &q->fence); + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); } /* Free the fence */ if (q->fence) - vkDestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc); + vk->DestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc); /* Free buffer dependencies */ for (int j = 0; j < q->nb_buf_deps; j++) @@ -1371,9 +1404,9 @@ static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) } if (e->bufs) - vkFreeCommandBuffers(s->hwctx->act_dev, e->pool, s->queue_count, e->bufs); + vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, s->queue_count, e->bufs); if (e->pool) - vkDestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); + vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); av_freep(&e->bufs); av_freep(&e->queues); @@ -1387,31 +1420,33 @@ static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) { + FFVulkanFunctions *vk = &s->vkfn; + for (int i = 0; i < pl->shaders_num; i++) { SPIRVShader *shd = pl->shaders[i]; av_bprint_finalize(&shd->src, NULL); - vkDestroyShaderModule(s->hwctx->act_dev, shd->shader.module, - s->hwctx->alloc); + vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, + s->hwctx->alloc); av_free(shd); } - vkDestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); - vkDestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout, - s->hwctx->alloc); + vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); + vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout, + s->hwctx->alloc); for (int i = 0; i < pl->desc_layout_num; i++) { if (pl->desc_template && pl->desc_template[i]) - vkDestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i], - s->hwctx->alloc); + vk->DestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i], + s->hwctx->alloc); if (pl->desc_layout && pl->desc_layout[i]) - vkDestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i], - s->hwctx->alloc); + vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i], + s->hwctx->alloc); } /* Also frees the descriptor sets */ if (pl->desc_pool) - vkDestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, - s->hwctx->alloc); + vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, + s->hwctx->alloc); av_freep(&pl->desc_set); av_freep(&pl->shaders); @@ -1434,6 +1469,7 @@ static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) void ff_vk_filter_uninit(AVFilterContext *avctx) { VulkanFilterContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; glslang_uninit(); @@ -1442,7 +1478,7 @@ void ff_vk_filter_uninit(AVFilterContext *avctx) av_freep(&s->exec_ctx); for (int i = 0; i < s->samplers_num; i++) { - vkDestroySampler(s->hwctx->act_dev, *s->samplers[i], s->hwctx->alloc); + vk->DestroySampler(s->hwctx->act_dev, *s->samplers[i], s->hwctx->alloc); av_free(s->samplers[i]); } av_freep(&s->samplers); diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index fa77995075..da5936dd43 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -19,11 +19,14 @@ #ifndef AVFILTER_VULKAN_H #define AVFILTER_VULKAN_H +#define VK_NO_PROTOTYPES + #include "avfilter.h" #include "libavutil/pixdesc.h" #include "libavutil/bprint.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vulkan.h" +#include "libavutil/vulkan_functions.h" /* GLSL management macros */ #define INDENT(N) INDENT_##N @@ -153,6 +156,8 @@ typedef struct FFVkExecContext { typedef struct VulkanFilterContext { const AVClass *class; + FFVulkanFunctions vkfn; + FFVulkanExtensions extensions; AVBufferRef *device_ref; AVBufferRef *frames_ref; /* For in-place filtering */ From 246f841b53e16f2cccf3101cb61c264014f54e5c Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 8 Nov 2021 09:31:05 +0100 Subject: [PATCH 120/894] lavfi/glslang: migrate to the C API and robustify library detection Finally, this is as close to usable as it gets for glslang. Much faster to compile as well, and eliminates the need for a C++ compiler, which is great. Also, changes to the resource limits won't break users, as we can use designated initializers in C90. --- configure | 15 +- libavfilter/glslang.c | 256 ++++++++++++++++++++++++++++++ libavfilter/glslang.cpp | 241 ---------------------------- libavfilter/glslang.h | 41 ++--- libavfilter/vf_avgblur_vulkan.c | 2 +- libavfilter/vf_chromaber_vulkan.c | 4 +- libavfilter/vf_overlay_vulkan.c | 4 +- libavfilter/vf_scale_vulkan.c | 4 +- libavfilter/vulkan.c | 63 +++----- libavfilter/vulkan.h | 21 ++- 10 files changed, 325 insertions(+), 326 deletions(-) create mode 100644 libavfilter/glslang.c delete mode 100644 libavfilter/glslang.cpp diff --git a/configure b/configure index 804bbe4c53..eb451d2782 100755 --- a/configure +++ b/configure @@ -3564,7 +3564,7 @@ ass_filter_deps="libass" atempo_filter_deps="avcodec" atempo_filter_select="rdft" avgblur_opencl_filter_deps="opencl" -avgblur_vulkan_filter_deps="libglslang" +avgblur_vulkan_filter_deps="vulkan libglslang" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" bm3d_filter_deps="avcodec" @@ -3572,7 +3572,7 @@ bm3d_filter_select="dct" boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" -chromaber_vulkan_filter_deps="libglslang" +chromaber_vulkan_filter_deps="vulkan libglslang" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" convolution_opencl_filter_deps="opencl" @@ -3635,7 +3635,7 @@ openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" -overlay_vulkan_filter_deps="libglslang" +overlay_vulkan_filter_deps="vulkan libglslang" owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" @@ -3698,7 +3698,7 @@ zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" -scale_vulkan_filter_deps="libglslang" +scale_vulkan_filter_deps="vulkan libglslang" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" xfade_opencl_filter_deps="opencl" @@ -6440,7 +6440,12 @@ enabled fontconfig && enable libfontconfig enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info -enabled libglslang && require_cpp libglslang glslang/SPIRV/GlslangToSpv.h "glslang::TIntermediate*" -lglslang -lMachineIndependent -lOSDependent -lHLSL -lOGLCompiler -lGenericCodeGen -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ +enabled libglslang && { check_lib libglslang glslang/Include/glslang_c_interface.h glslang_initialize_process \ + -lglslang -lMachineIndependent -lOSDependent -lHLSL -lOGLCompiler -lGenericCodeGen \ + -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm || + require libglslang glslang/Include/glslang_c_interface.h glslang_initialize_process \ + -lglslang -lOSDependent -lHLSL -lOGLCompiler \ + -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm; } enabled libgme && { check_pkg_config libgme libgme gme/gme.h gme_new_emu || require libgme gme/gme.h gme_new_emu -lgme -lstdc++; } enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do diff --git a/libavfilter/glslang.c b/libavfilter/glslang.c new file mode 100644 index 0000000000..e5a8d4dc2a --- /dev/null +++ b/libavfilter/glslang.c @@ -0,0 +1,256 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "libavutil/mem.h" +#include "libavutil/avassert.h" + +#include "glslang.h" + +static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; +static int glslang_refcount = 0; + +static const glslang_resource_t glslc_resource_limits = { + .max_lights = 32, + .max_clip_planes = 6, + .max_texture_units = 32, + .max_texture_coords = 32, + .max_vertex_attribs = 64, + .max_vertex_uniform_components = 4096, + .max_varying_floats = 64, + .max_vertex_texture_image_units = 32, + .max_combined_texture_image_units = 80, + .max_texture_image_units = 32, + .max_fragment_uniform_components = 4096, + .max_draw_buffers = 32, + .max_vertex_uniform_vectors = 128, + .max_varying_vectors = 8, + .max_fragment_uniform_vectors = 16, + .max_vertex_output_vectors = 16, + .max_fragment_input_vectors = 15, + .min_program_texel_offset = -8, + .max_program_texel_offset = 7, + .max_clip_distances = 8, + .max_compute_work_group_count_x = 65535, + .max_compute_work_group_count_y = 65535, + .max_compute_work_group_count_z = 65535, + .max_compute_work_group_size_x = 1024, + .max_compute_work_group_size_y = 1024, + .max_compute_work_group_size_z = 64, + .max_compute_uniform_components = 1024, + .max_compute_texture_image_units = 16, + .max_compute_image_uniforms = 8, + .max_compute_atomic_counters = 8, + .max_compute_atomic_counter_buffers = 1, + .max_varying_components = 60, + .max_vertex_output_components = 64, + .max_geometry_input_components = 64, + .max_geometry_output_components = 128, + .max_fragment_input_components = 128, + .max_image_units = 8, + .max_combined_image_units_and_fragment_outputs = 8, + .max_combined_shader_output_resources = 8, + .max_image_samples = 0, + .max_vertex_image_uniforms = 0, + .max_tess_control_image_uniforms = 0, + .max_tess_evaluation_image_uniforms = 0, + .max_geometry_image_uniforms = 0, + .max_fragment_image_uniforms = 8, + .max_combined_image_uniforms = 8, + .max_geometry_texture_image_units = 16, + .max_geometry_output_vertices = 256, + .max_geometry_total_output_components = 1024, + .max_geometry_uniform_components = 1024, + .max_geometry_varying_components = 64, + .max_tess_control_input_components = 128, + .max_tess_control_output_components = 128, + .max_tess_control_texture_image_units = 16, + .max_tess_control_uniform_components = 1024, + .max_tess_control_total_output_components = 4096, + .max_tess_evaluation_input_components = 128, + .max_tess_evaluation_output_components = 128, + .max_tess_evaluation_texture_image_units = 16, + .max_tess_evaluation_uniform_components = 1024, + .max_tess_patch_components = 120, + .max_patch_vertices = 32, + .max_tess_gen_level = 64, + .max_viewports = 16, + .max_vertex_atomic_counters = 0, + .max_tess_control_atomic_counters = 0, + .max_tess_evaluation_atomic_counters = 0, + .max_geometry_atomic_counters = 0, + .max_fragment_atomic_counters = 8, + .max_combined_atomic_counters = 8, + .max_atomic_counter_bindings = 1, + .max_vertex_atomic_counter_buffers = 0, + .max_tess_control_atomic_counter_buffers = 0, + .max_tess_evaluation_atomic_counter_buffers = 0, + .max_geometry_atomic_counter_buffers = 0, + .max_fragment_atomic_counter_buffers = 1, + .max_combined_atomic_counter_buffers = 1, + .max_atomic_counter_buffer_size = 16384, + .max_transform_feedback_buffers = 4, + .max_transform_feedback_interleaved_components = 64, + .max_cull_distances = 8, + .max_combined_clip_and_cull_distances = 8, + .max_samples = 4, + .max_mesh_output_vertices_nv = 256, + .max_mesh_output_primitives_nv = 512, + .max_mesh_work_group_size_x_nv = 32, + .max_mesh_work_group_size_y_nv = 1, + .max_mesh_work_group_size_z_nv = 1, + .max_task_work_group_size_x_nv = 32, + .max_task_work_group_size_y_nv = 1, + .max_task_work_group_size_z_nv = 1, + .max_mesh_view_count_nv = 4, + .maxDualSourceDrawBuffersEXT = 1, + + .limits = { + .non_inductive_for_loops = 1, + .while_loops = 1, + .do_while_loops = 1, + .general_uniform_indexing = 1, + .general_attribute_matrix_vector_indexing = 1, + .general_varying_indexing = 1, + .general_sampler_indexing = 1, + .general_variable_indexing = 1, + .general_constant_matrix_vector_indexing = 1, + } +}; + +int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, + uint8_t **data, size_t *size, void **opaque) +{ + const char *messages; + glslang_shader_t *glslc_shader; + glslang_program_t *glslc_program; + + static const glslang_stage_t glslc_stage[] = { + [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_STAGE_VERTEX, + [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT, + [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_STAGE_COMPUTE, + }; + + const glslang_input_t glslc_input = { + .language = GLSLANG_SOURCE_GLSL, + .stage = glslc_stage[shd->shader.stage], + .client = GLSLANG_CLIENT_VULKAN, + /* GLSLANG_TARGET_VULKAN_1_2 before 11.6 resulted in targeting 1.0 */ +#if (((GLSLANG_VERSION_MAJOR) > 11) || ((GLSLANG_VERSION_MAJOR) == 11 && \ + (((GLSLANG_VERSION_MINOR) > 6) || ((GLSLANG_VERSION_MINOR) == 6 && \ + ((GLSLANG_VERSION_PATCH) > 0))))) + .client_version = GLSLANG_TARGET_VULKAN_1_2, + .target_language_version = GLSLANG_TARGET_SPV_1_5, +#else + .client_version = GLSLANG_TARGET_VULKAN_1_1, + .target_language_version = GLSLANG_TARGET_SPV_1_3, +#endif + .target_language = GLSLANG_TARGET_SPV, + .code = shd->src.str, + .default_version = 460, + .default_profile = GLSLANG_NO_PROFILE, + .force_default_version_and_profile = false, + .forward_compatible = false, + .messages = GLSLANG_MSG_DEFAULT_BIT, + .resource = &glslc_resource_limits, + }; + + av_assert0(glslang_refcount); + + if (!(glslc_shader = glslang_shader_create(&glslc_input))) + return AVERROR(ENOMEM); + + if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!glslang_shader_parse(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!(glslc_program = glslang_program_create())) { + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_add_shader(glslc_program, glslc_shader); + + if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT | + GLSLANG_MSG_VULKAN_RULES_BIT)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n", + glslang_program_get_info_log(glslc_program), + glslang_program_get_info_debug_log(glslc_program)); + glslang_program_delete(glslc_program); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); + + messages = glslang_program_SPIRV_get_messages(glslc_program); + if (messages) + av_log(avctx, AV_LOG_WARNING, "%s\n", messages); + + glslang_shader_delete(glslc_shader); + + *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int); + *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program); + *opaque = glslc_program; + + return 0; +} + +void ff_vk_glslang_shader_free(void *opaque) +{ + glslang_program_delete(opaque); +} + +int ff_vk_glslang_init(void) +{ + int ret = 0; + + pthread_mutex_lock(&glslang_mutex); + if (glslang_refcount++ == 0) + ret = !glslang_initialize_process(); + pthread_mutex_unlock(&glslang_mutex); + + return ret; +} + +void ff_vk_glslang_uninit(void) +{ + pthread_mutex_lock(&glslang_mutex); + if (glslang_refcount && (--glslang_refcount == 0)) + glslang_finalize_process(); + pthread_mutex_unlock(&glslang_mutex); +} diff --git a/libavfilter/glslang.cpp b/libavfilter/glslang.cpp deleted file mode 100644 index 986bddd789..0000000000 --- a/libavfilter/glslang.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -extern "C" { -#include "libavutil/mem.h" -#include "libavutil/avassert.h" -} - -#include -#include -#include - -#include "glslang.h" - -using namespace glslang; - -static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; -static int glslang_refcount = 0; - -/* We require Vulkan 1.1 */ -#define GLSL_VERSION EShTargetVulkan_1_1 - -/* Vulkan 1.1 implementations require SPIR-V 1.3 to be implemented */ -#define SPIRV_VERSION EShTargetSpv_1_3 - -// Taken from glslang's examples, which apparently generally bases the choices -// on OpenGL specification limits -static const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - - .limits = { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - } -}; - -GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage) -{ - GLSlangResult *res = (GLSlangResult *)av_mallocz(sizeof(*res)); - if (!res) - return NULL; - - static const EShLanguage lang[] = { - [GLSLANG_VERTEX] = EShLangVertex, - [GLSLANG_FRAGMENT] = EShLangFragment, - [GLSLANG_COMPUTE] = EShLangCompute, - }; - - assert(glslang_refcount); - TShader *shader = new TShader(lang[stage]); - if (!shader) { - res->rval = AVERROR(ENOMEM); - return res; - } - - shader->setEnvClient(EShClientVulkan, GLSL_VERSION); - shader->setEnvTarget(EShTargetSpv, SPIRV_VERSION); - shader->setStrings(&glsl, 1); - if (!shader->parse(&DefaultTBuiltInResource, GLSL_VERSION, true, EShMsgDefault)) { - res->error_msg = av_strdup(shader->getInfoLog()); - res->rval = AVERROR_EXTERNAL; - delete shader; - return res; - } - - TProgram *prog = new TProgram(); - if (!prog) { - res->rval = AVERROR(ENOMEM); - delete shader; - return res; - } - - prog->addShader(shader); - if (!prog->link(EShMsgDefault)) { - res->error_msg = av_strdup(prog->getInfoLog()); - res->rval = AVERROR_EXTERNAL; - delete shader; - delete prog; - return res; - } - - std::vector spirv; /* Result */ - - SpvOptions options; /* Options - by default all optimizations are off */ - options.generateDebugInfo = false; /* Makes sense for files but not here */ - options.disassemble = false; /* Will print disassembly on compilation */ - options.validate = false; /* Validates the generated SPIRV, unneeded */ - options.disableOptimizer = false; /* For debugging */ - options.optimizeSize = true; /* Its faster */ - - GlslangToSpv(*prog->getIntermediate(lang[stage]), spirv, NULL, &options); - - res->size = spirv.size()*sizeof(unsigned int); - res->data = av_memdup(spirv.data(), res->size); - if (!res->data) { - res->rval = AVERROR(ENOMEM); - delete shader; - delete prog; - return res; - } - - delete shader; - delete prog; - - return res; -} - -int glslang_init(void) -{ - int ret = 0; - - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount++ == 0) - ret = !InitializeProcess(); - pthread_mutex_unlock(&glslang_mutex); - - return ret; -} - -void glslang_uninit(void) -{ - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount && (--glslang_refcount == 0)) - FinalizeProcess(); - pthread_mutex_unlock(&glslang_mutex); -} diff --git a/libavfilter/glslang.h b/libavfilter/glslang.h index d33808b945..93a077dbfc 100644 --- a/libavfilter/glslang.h +++ b/libavfilter/glslang.h @@ -19,34 +19,23 @@ #ifndef AVFILTER_GLSLANG_H #define AVFILTER_GLSLANG_H -#include +#include "vulkan.h" -#ifdef __cplusplus -extern "C" { -#endif +/** + * Un/initialize glslang's global state. Thread-safe and reference counted. + */ +int ff_vk_glslang_init(void); +void ff_vk_glslang_uninit(void); -int glslang_init(void); -void glslang_uninit(void); +/** + * Compile GLSL into SPIR-V using glslang. + */ +int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, + uint8_t **data, size_t *size, void **opaque); -typedef struct GLSlangResult { - int rval; - char *error_msg; - - void *data; /* Shader data or NULL */ - size_t size; -} GLSlangResult; - -enum GLSlangStage { - GLSLANG_VERTEX, - GLSLANG_FRAGMENT, - GLSLANG_COMPUTE, -}; - -/* Compile GLSL into a SPIRV stream, if possible */ -GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage); - -#ifdef __cplusplus -} -#endif +/** + * Frees the shader-specific context. + */ +void ff_vk_glslang_shader_free(void *opaque); #endif /* AVFILTER_GLSLANG_H */ diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 158ccf02df..bf02dab1db 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -70,7 +70,7 @@ static const char blur_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - SPIRVShader *shd; + FFSPIRVShader *shd; AvgBlurVulkanContext *s = ctx->priv; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 2503972c2a..25ef20fe73 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -109,8 +109,8 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 77b3668819..f08800af2c 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -136,8 +136,8 @@ static av_cold int init_filter(AVFilterContext *ctx) .buf_content = "ivec2 o_offset[3], o_size[3];", }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 83e101954b..680e9c2f4f 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -170,8 +170,8 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .buf_content = "mat4 yuv_matrix;", }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index 4ac8e5e90a..c9a2ae4593 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -794,7 +794,7 @@ int ff_vk_filter_init(AVFilterContext *avctx) s->output_format = AV_PIX_FMT_NONE; - if (glslang_init()) + if (ff_vk_glslang_init()) return AVERROR_EXTERNAL; return 0; @@ -924,11 +924,11 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, return 0; } -FN_CREATING(VulkanPipeline, SPIRVShader, shader, shaders, shaders_num) -SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, - const char *name, VkShaderStageFlags stage) +FN_CREATING(VulkanPipeline, FFSPIRVShader, shader, shaders, shaders_num) +FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, + const char *name, VkShaderStageFlags stage) { - SPIRVShader *shd = create_shader(pl); + FFSPIRVShader *shd = create_shader(pl); if (!shd) return NULL; @@ -946,7 +946,7 @@ SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, return shd; } -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, +void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, int local_size[3]) { shd->local_size[0] = local_size[0]; @@ -958,7 +958,7 @@ void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, shd->local_size[0], shd->local_size[1], shd->local_size[2]); } -static void print_shader(AVFilterContext *avctx, SPIRVShader *shd, int prio) +void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio) { int line = 0; const char *p = shd->src.str; @@ -979,51 +979,39 @@ static void print_shader(AVFilterContext *avctx, SPIRVShader *shd, int prio) av_bprint_finalize(&buf, NULL); } -int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, +int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, const char *entrypoint) { + int err; VkResult ret; VulkanFilterContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkShaderModuleCreateInfo shader_create; - GLSlangResult *res; - - static const enum GLSlangStage emap[] = { - [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_VERTEX, - [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_FRAGMENT, - [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_COMPUTE, - }; + uint8_t *spirv; + size_t spirv_size; + void *priv; shd->shader.pName = entrypoint; - res = glslang_compile(shd->src.str, emap[shd->shader.stage]); - if (!res) - return AVERROR(ENOMEM); + err = ff_vk_glslang_shader_compile(avctx, shd, &spirv, &spirv_size, &priv); + if (err < 0) + return err; - if (res->rval) { - av_log(avctx, AV_LOG_ERROR, "Error compiling shader %s: %s!\n", - shd->name, av_err2str(res->rval)); - print_shader(avctx, shd, AV_LOG_ERROR); - if (res->error_msg) - av_log(avctx, AV_LOG_ERROR, "%s", res->error_msg); - av_free(res->error_msg); - return res->rval; - } + ff_vk_print_shader(avctx, shd, AV_LOG_VERBOSE); - print_shader(avctx, shd, AV_LOG_VERBOSE); + av_log(avctx, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", + shd->name, spirv_size); shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; shader_create.pNext = NULL; - shader_create.codeSize = res->size; + shader_create.codeSize = spirv_size; shader_create.flags = 0; - shader_create.pCode = res->data; + shader_create.pCode = (void *)spirv; ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, &shd->shader.module); - /* Free the GLSlangResult struct */ - av_free(res->data); - av_free(res); + ff_vk_glslang_shader_free(priv); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to create shader module: %s\n", @@ -1031,9 +1019,6 @@ int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, return AVERROR_EXTERNAL; } - av_log(avctx, AV_LOG_VERBOSE, "Shader %s linked! Size: %zu bytes\n", - shd->name, shader_create.codeSize); - return 0; } @@ -1059,7 +1044,7 @@ static const struct descriptor_props { }; int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - SPIRVShader *shd, VulkanDescriptorSetBinding *desc, + FFSPIRVShader *shd, VulkanDescriptorSetBinding *desc, int num, int only_print_to_shader) { VkResult ret; @@ -1423,7 +1408,7 @@ static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) FFVulkanFunctions *vk = &s->vkfn; for (int i = 0; i < pl->shaders_num; i++) { - SPIRVShader *shd = pl->shaders[i]; + FFSPIRVShader *shd = pl->shaders[i]; av_bprint_finalize(&shd->src, NULL); vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, s->hwctx->alloc); @@ -1471,7 +1456,7 @@ void ff_vk_filter_uninit(AVFilterContext *avctx) VulkanFilterContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - glslang_uninit(); + ff_vk_glslang_uninit(); for (int i = 0; i < s->exec_ctx_num; i++) free_exec_ctx(s, s->exec_ctx[i]); diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index da5936dd43..89b76ba355 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -55,12 +55,12 @@ /* Useful for attaching immutable samplers to arrays */ #define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, } -typedef struct SPIRVShader { +typedef struct FFSPIRVShader { const char *name; /* Name for id/debugging purposes */ AVBPrint src; int local_size[3]; /* Compute shader workgroup sizes */ VkPipelineShaderStageCreateInfo shader; -} SPIRVShader; +} FFSPIRVShader; typedef struct VulkanDescriptorSetBinding { const char *name; @@ -89,7 +89,7 @@ typedef struct VulkanPipeline { VkPipeline pipeline; /* Shaders */ - SPIRVShader **shaders; + FFSPIRVShader **shaders; int shaders_num; /* Push consts */ @@ -249,28 +249,33 @@ VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx); /** * Inits a shader for a specific pipeline. Will be auto-freed on uninit. */ -SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, - const char *name, VkShaderStageFlags stage); +FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, + const char *name, VkShaderStageFlags stage); /** * Writes the workgroup size for a shader. */ -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, +void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, int local_size[3]); /** * Adds a descriptor set to the shader and registers them in the pipeline. */ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - SPIRVShader *shd, VulkanDescriptorSetBinding *desc, + FFSPIRVShader *shd, VulkanDescriptorSetBinding *desc, int num, int only_print_to_shader); /** * Compiles the shader, entrypoint must be set to "main". */ -int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, +int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, const char *entrypoint); +/** + * Pretty print shader, mainly used by shader compilers. + */ +void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio); + /** * Initializes the pipeline layout after all shaders and descriptor sets have * been finished. From f705e9ea0567c8dcf800ae1ee0647fca157c6199 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 10 Nov 2021 03:50:54 +0100 Subject: [PATCH 121/894] lavfi/vulkan: refactor, fix and fully implement multiple queues --- libavfilter/vf_avgblur_vulkan.c | 27 +-- libavfilter/vf_chromaber_vulkan.c | 25 ++- libavfilter/vf_overlay_vulkan.c | 30 +-- libavfilter/vf_scale_vulkan.c | 27 +-- libavfilter/vulkan.c | 340 ++++++++++++++++++------------ libavfilter/vulkan.h | 103 +++++---- 6 files changed, 336 insertions(+), 216 deletions(-) diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index bf02dab1db..4795e482a9 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -24,12 +24,13 @@ #define CGS 32 typedef struct AvgBlurVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; - VulkanPipeline *pl_hor; - VulkanPipeline *pl_ver; + FFVulkanPipeline *pl_hor; + FFVulkanPipeline *pl_ver; /* Shader updators, must be in the main filter struct */ VkDescriptorImageInfo input_images[3]; @@ -73,16 +74,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) FFSPIRVShader *shd; AvgBlurVulkanContext *s = ctx->priv; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); - VulkanDescriptorSetBinding desc_i[2] = { + FFVulkanDescriptorSetBinding desc_i[2] = { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), }, { .name = "output_img", @@ -95,17 +94,17 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - if (!sampler) - return AVERROR_EXTERNAL; + ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; + desc_i[0].sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); + if (!desc_i[0].sampler) + return AVERROR_EXTERNAL; { /* Create shader for the horizontal pass */ desc_i[0].updater = s->input_images; desc_i[1].updater = s->tmp_images; - s->pl_hor = ff_vk_create_pipeline(ctx); + s->pl_hor = ff_vk_create_pipeline(ctx, &s->qf); if (!s->pl_hor) return AVERROR(ENOMEM); @@ -148,7 +147,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) desc_i[0].updater = s->tmp_images; desc_i[1].updater = s->output_images; - s->pl_ver = ff_vk_create_pipeline(ctx); + s->pl_ver = ff_vk_create_pipeline(ctx, &s->qf); if (!s->pl_ver) return AVERROR(ENOMEM); @@ -188,7 +187,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); s->initialized = 1; @@ -311,6 +310,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 25ef20fe73..83ab72f716 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -24,11 +24,12 @@ #define CGROUPS (int [3]){ 32, 32, 1 } typedef struct ChromaticAberrationVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; - VulkanPipeline *pl; + FFVulkanPipeline *pl; /* Shader updators, must be in the main filter struct */ VkDescriptorImageInfo input_images[3]; @@ -67,17 +68,18 @@ static const char distort_chroma_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; + FFVkSampler *sampler; ChromaticAberrationVulkanContext *s = ctx->priv; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); /* Create a sampler */ - VkSampler *sampler = ff_vk_init_sampler(ctx, 0, VK_FILTER_LINEAR); + sampler = ff_vk_init_sampler(ctx, 0, VK_FILTER_LINEAR); if (!sampler) return AVERROR_EXTERNAL; - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; - - s->pl = ff_vk_create_pipeline(ctx); + s->pl = ff_vk_create_pipeline(ctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); @@ -86,8 +88,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) s->opts.dist[1] = (s->opts.dist[1] / 100.0f) + 1.0f; { /* Create the shader */ - const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - VulkanDescriptorSetBinding desc_i[2] = { + FFVulkanDescriptorSetBinding desc_i[2] = { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -95,7 +96,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->input_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "output_img", @@ -158,7 +159,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) RET(ff_vk_init_compute_pipeline(ctx, s->pl)); /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); s->initialized = 1; @@ -256,6 +257,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index f08800af2c..b902ad83f5 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -25,11 +25,12 @@ #define CGROUPS (int [3]){ 32, 32, 1 } typedef struct OverlayVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; - VulkanPipeline *pl; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; + FFVulkanPipeline *pl; FFFrameSync fs; FFVkBuffer params_buf; @@ -79,23 +80,24 @@ static const char overlay_alpha[] = { static av_cold int init_filter(AVFilterContext *ctx) { int err; + FFVkSampler *sampler; OverlayVulkanContext *s = ctx->priv; - VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_NEAREST); + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_NEAREST); if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx); + s->pl = ff_vk_create_pipeline(ctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; - { /* Create the shader */ - const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA; - VulkanDescriptorSetBinding desc_i[3] = { + FFVulkanDescriptorSetBinding desc_i[3] = { { .name = "main_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -103,7 +105,7 @@ static av_cold int init_filter(AVFilterContext *ctx) .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->main_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "overlay_img", @@ -112,7 +114,7 @@ static av_cold int init_filter(AVFilterContext *ctx) .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->overlay_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "output_img", @@ -126,7 +128,7 @@ static av_cold int init_filter(AVFilterContext *ctx) }, }; - VulkanDescriptorSetBinding desc_b = { + FFVulkanDescriptorSetBinding desc_b = { .name = "params", .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .mem_quali = "readonly", @@ -215,7 +217,7 @@ static av_cold int init_filter(AVFilterContext *ctx) } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); s->initialized = 1; @@ -339,6 +341,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 680e9c2f4f..3a2251f8df 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -33,11 +33,12 @@ enum ScalerFunc { }; typedef struct ScaleVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; - VulkanPipeline *pl; + FFVulkanPipeline *pl; FFVkBuffer params_buf; /* Shader updators, must be in the main filter struct */ @@ -107,7 +108,7 @@ static const char write_444[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - VkSampler *sampler; + FFVkSampler *sampler; VkFilter sampler_mode; ScaleVulkanContext *s = ctx->priv; @@ -115,9 +116,9 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) int crop_y = in->crop_top; int crop_w = in->width - (in->crop_left + in->crop_right); int crop_h = in->height - (in->crop_top + in->crop_bottom); + int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format); - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = s->vkctx.hwctx->nb_comp_queues; + ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); switch (s->scaler) { case F_NEAREST: @@ -133,20 +134,20 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx); + s->pl = ff_vk_create_pipeline(ctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); { /* Create the shader */ - VulkanDescriptorSetBinding desc_i[2] = { + FFVulkanDescriptorSetBinding desc_i[2] = { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, - .elems = av_pix_fmt_count_planes(s->vkctx.input_format), + .elems = in_planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->input_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "output_img", @@ -160,7 +161,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - VulkanDescriptorSetBinding desc_b = { + FFVulkanDescriptorSetBinding desc_b = { .name = "params", .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .mem_quali = "readonly", @@ -178,7 +179,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( scale_bilinear ); @@ -280,7 +281,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); s->initialized = 1; @@ -384,6 +385,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index c9a2ae4593..a30699963e 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -20,6 +20,7 @@ #include "vulkan.h" #include "glslang.h" +#include "libavutil/avassert.h" #include "libavutil/vulkan_loader.h" /* Generic macro for creating contexts which need to keep their addresses @@ -88,15 +89,54 @@ const char *ff_vk_ret2str(VkResult res) #undef CASE } +void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int queue_limit) +{ + FFVulkanContext *s = avctx->priv; + + if (!queue_limit) + queue_limit = INT32_MAX; + + switch (dev_family) { + case VK_QUEUE_GRAPHICS_BIT: + qf->queue_family = s->hwctx->queue_family_index; + qf->nb_queues = FFMIN(s->hwctx->nb_graphics_queues, queue_limit); + return; + case VK_QUEUE_COMPUTE_BIT: + qf->queue_family = s->hwctx->queue_family_comp_index; + qf->nb_queues = FFMIN(s->hwctx->nb_comp_queues, queue_limit); + return; + case VK_QUEUE_TRANSFER_BIT: + qf->queue_family = s->hwctx->queue_family_tx_index; + qf->nb_queues = FFMIN(s->hwctx->nb_tx_queues, queue_limit); + return; + case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: + qf->queue_family = s->hwctx->queue_family_encode_index; + qf->nb_queues = FFMIN(s->hwctx->nb_encode_queues, queue_limit); + return; + case VK_QUEUE_VIDEO_DECODE_BIT_KHR: + qf->queue_family = s->hwctx->queue_family_decode_index; + qf->nb_queues = FFMIN(s->hwctx->nb_decode_queues, queue_limit); + return; + default: + av_assert0(0); /* Should never happen */ + } + + return; +} + +void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) +{ + qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues; +} + static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) { VkResult ret; int index = -1; - VkPhysicalDeviceProperties props; - VkPhysicalDeviceMemoryProperties mprops; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkMemoryAllocateInfo alloc_info = { @@ -104,24 +144,21 @@ static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, .pNext = alloc_extension, }; - vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &props); - vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &mprops); - /* Align if we need to */ if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) - req->size = FFALIGN(req->size, props.limits.minMemoryMapAlignment); + req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment); alloc_info.allocationSize = req->size; /* The vulkan spec requires memory types to be sorted in the "optimal" * order, so the first matching type we find will be the best/fastest one */ - for (int i = 0; i < mprops.memoryTypeCount; i++) { + for (int i = 0; i < s->mprops.memoryTypeCount; i++) { /* The memory type must be supported by the requirements (bitfield) */ if (!(req->memoryTypeBits & (1 << i))) continue; /* The memory type flags must include our properties */ - if ((mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) + if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) continue; /* Found a suitable memory type */ @@ -145,7 +182,7 @@ static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, return AVERROR(ENOMEM); } - *mem_flags |= mprops.memoryTypes[index].propertyFlags; + *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; return 0; } @@ -156,7 +193,7 @@ int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, int err; VkResult ret; int use_ded_mem; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkBufferCreateInfo buf_spawn = { @@ -220,7 +257,7 @@ int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], int nb_buffers, int invalidate) { VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkMappedMemoryRange *inval_list = NULL; int inval_count = 0; @@ -271,7 +308,7 @@ int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, { int err = 0; VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkMappedMemoryRange *flush_list = NULL; int flush_count = 0; @@ -311,7 +348,7 @@ int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; if (!buf) @@ -323,7 +360,7 @@ void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf) vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); } -int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl, +int ff_vk_add_push_constant(AVFilterContext *avctx, FFVulkanPipeline *pl, int offset, int size, VkShaderStageFlagBits stage) { VkPushConstantRange *pc; @@ -343,37 +380,37 @@ int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl, return 0; } -FN_CREATING(VulkanFilterContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) -int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) +FN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) +int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx, + FFVkQueueFamilyCtx *qf) { VkResult ret; FFVkExecContext *e; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - int queue_family = s->queue_family_idx; - int nb_queues = s->queue_count; - VkCommandPoolCreateInfo cqueue_create = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = queue_family, + .queueFamilyIndex = qf->queue_family, }; VkCommandBufferAllocateInfo cbuf_create = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = nb_queues, + .commandBufferCount = qf->nb_queues, }; e = create_exec_ctx(s); if (!e) return AVERROR(ENOMEM); - e->queues = av_mallocz(nb_queues * sizeof(*e->queues)); + e->qf = qf; + + e->queues = av_mallocz(qf->nb_queues * sizeof(*e->queues)); if (!e->queues) return AVERROR(ENOMEM); - e->bufs = av_mallocz(nb_queues * sizeof(*e->bufs)); + e->bufs = av_mallocz(qf->nb_queues * sizeof(*e->bufs)); if (!e->bufs) return AVERROR(ENOMEM); @@ -396,9 +433,9 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) return AVERROR_EXTERNAL; } - for (int i = 0; i < nb_queues; i++) { + for (int i = 0; i < qf->nb_queues; i++) { FFVkQueueCtx *q = &e->queues[i]; - vk->GetDeviceQueue(s->hwctx->act_dev, queue_family, i, &q->queue); + vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, i, &q->queue); } *ctx = e; @@ -408,8 +445,7 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e) { - VulkanFilterContext *s = avctx->priv; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; for (int j = 0; j < q->nb_buf_deps; j++) av_buffer_unref(&q->buf_deps[j]); @@ -426,9 +462,9 @@ void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e) int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) { VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; VkCommandBufferBeginInfo cmd_start = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -455,7 +491,7 @@ int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) /* Discard queue dependencies */ ff_vk_discard_exec_deps(avctx, e); - ret = vk->BeginCommandBuffer(e->bufs[s->cur_queue_idx], &cmd_start); + ret = vk->BeginCommandBuffer(e->bufs[e->qf->cur_queue], &cmd_start); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to start command recoding: %s\n", ff_vk_ret2str(ret)); @@ -467,17 +503,15 @@ int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e) { - VulkanFilterContext *s = avctx->priv; - return e->bufs[s->cur_queue_idx]; + return e->bufs[e->qf->cur_queue]; } int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag) { AVFrame **dst; - VulkanFilterContext *s = avctx->priv; AVVkFrame *f = (AVVkFrame *)frame->data[0]; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data; int planes = av_pix_fmt_count_planes(fc->sw_format); @@ -517,16 +551,21 @@ int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, return AVERROR(ENOMEM); } + e->sem_sig_val_dst = av_fast_realloc(e->sem_sig_val_dst, &e->sem_sig_val_dst_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val_dst)); + if (!e->sem_sig_val_dst) { + ff_vk_discard_exec_deps(avctx, e); + return AVERROR(ENOMEM); + } + e->sem_wait[e->sem_wait_cnt] = f->sem[i]; e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag; e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i]; e->sem_wait_cnt++; - /* TODO: fix this in case execution fails */ - f->sem_value[i]++; - e->sem_sig[e->sem_sig_cnt] = f->sem[i]; - e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i]; + e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i] + 1; + e->sem_sig_val_dst[e->sem_sig_cnt] = &f->sem_value[i]; e->sem_sig_cnt++; } @@ -551,9 +590,9 @@ int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) { VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, @@ -568,7 +607,7 @@ int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) .pNext = &s_timeline_sem_info, .commandBufferCount = 1, - .pCommandBuffers = &e->bufs[s->cur_queue_idx], + .pCommandBuffers = &e->bufs[e->qf->cur_queue], .pWaitSemaphores = e->sem_wait, .pWaitDstStageMask = e->sem_wait_dst, @@ -578,7 +617,7 @@ int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) .signalSemaphoreCount = e->sem_sig_cnt, }; - ret = vk->EndCommandBuffer(e->bufs[s->cur_queue_idx]); + ret = vk->EndCommandBuffer(e->bufs[e->qf->cur_queue]); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", ff_vk_ret2str(ret)); @@ -592,8 +631,8 @@ int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) return AVERROR_EXTERNAL; } - /* Rotate queues */ - s->cur_queue_idx = (s->cur_queue_idx + 1) % s->queue_count; + for (int i = 0; i < e->sem_sig_cnt; i++) + *e->sem_sig_val_dst[i] += 1; return 0; } @@ -602,8 +641,7 @@ int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e, AVBufferRef **deps, int nb_deps) { AVBufferRef **dst; - VulkanFilterContext *s = avctx->priv; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; if (!deps || !nb_deps) return 0; @@ -632,7 +670,7 @@ err: static int vulkan_filter_set_device(AVFilterContext *avctx, AVBufferRef *device) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; av_buffer_unref(&s->device_ref); @@ -649,7 +687,7 @@ static int vulkan_filter_set_device(AVFilterContext *avctx, static int vulkan_filter_set_frames(AVFilterContext *avctx, AVBufferRef *frames) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; av_buffer_unref(&s->frames_ref); @@ -664,7 +702,8 @@ int ff_vk_filter_config_input(AVFilterLink *inlink) { int err; AVFilterContext *avctx = inlink->dst; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; AVHWFramesContext *input_frames; if (!inlink->hw_frames_ctx) { @@ -695,6 +734,9 @@ int ff_vk_filter_config_input(AVFilterLink *inlink) if (err < 0) return err; + vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &s->props); + vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); + /* Default output parameters match input parameters. */ s->input_format = input_frames->sw_format; if (s->output_format == AV_PIX_FMT_NONE) @@ -711,7 +753,7 @@ int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) { int err; AVFilterContext *avctx = outlink->src; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; av_buffer_unref(&outlink->hw_frames_ctx); @@ -741,7 +783,7 @@ int ff_vk_filter_config_output(AVFilterLink *outlink) { int err; AVFilterContext *avctx = outlink->src; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; AVBufferRef *output_frames_ref; AVHWFramesContext *output_frames; @@ -790,7 +832,7 @@ fail: int ff_vk_filter_init(AVFilterContext *avctx) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; s->output_format = AV_PIX_FMT_NONE; @@ -800,12 +842,12 @@ int ff_vk_filter_init(AVFilterContext *avctx) return 0; } -FN_CREATING(VulkanFilterContext, VkSampler, sampler, samplers, samplers_num) -VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, - VkFilter filt) +FN_CREATING(FFVulkanContext, FFVkSampler, sampler, samplers, samplers_num) +FFVkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, + VkFilter filt) { VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkSamplerCreateInfo sampler_info = { @@ -823,19 +865,22 @@ VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, .unnormalizedCoordinates = unnorm_coords, }; - VkSampler *sampler = create_sampler(s); - if (!sampler) + FFVkSampler *sctx = create_sampler(s); + if (!sctx) return NULL; ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info, - s->hwctx->alloc, sampler); + s->hwctx->alloc, &sctx->sampler[0]); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init sampler: %s\n", ff_vk_ret2str(ret)); return NULL; } - return sampler; + for (int i = 1; i < 4; i++) + sctx->sampler[i] = sctx->sampler[0]; + + return sctx; } int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt) @@ -863,7 +908,7 @@ typedef struct ImageViewCtx { static void destroy_imageview(void *opaque, uint8_t *data) { - VulkanFilterContext *s = opaque; + FFVulkanContext *s = opaque; FFVulkanFunctions *vk = &s->vkfn; ImageViewCtx *iv = (ImageViewCtx *)data; @@ -877,7 +922,7 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, { int err; AVBufferRef *buf; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkImageViewCreateInfo imgview_spawn = { @@ -924,8 +969,8 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, return 0; } -FN_CREATING(VulkanPipeline, FFSPIRVShader, shader, shaders, shaders_num) -FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, +FN_CREATING(FFVulkanPipeline, FFSPIRVShader, shader, shaders, shaders_num) +FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, FFVulkanPipeline *pl, const char *name, VkShaderStageFlags stage) { FFSPIRVShader *shd = create_shader(pl); @@ -984,7 +1029,7 @@ int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, { int err; VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkShaderModuleCreateInfo shader_create; uint8_t *spirv; @@ -1043,25 +1088,24 @@ static const struct descriptor_props { [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, }, }; -int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - FFSPIRVShader *shd, VulkanDescriptorSetBinding *desc, +int ff_vk_add_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, + FFSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, int num, int only_print_to_shader) { VkResult ret; VkDescriptorSetLayout *layout; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; if (only_print_to_shader) goto print; pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout), - pl->desc_layout_num + 1); + pl->desc_layout_num + pl->qf->nb_queues); if (!pl->desc_layout) return AVERROR(ENOMEM); layout = &pl->desc_layout[pl->desc_layout_num]; - memset(layout, 0, sizeof(*layout)); { /* Create descriptor set layout descriptions */ VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 }; @@ -1076,21 +1120,27 @@ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, desc_binding[i].descriptorType = desc[i].type; desc_binding[i].descriptorCount = FFMAX(desc[i].elems, 1); desc_binding[i].stageFlags = desc[i].stages; - desc_binding[i].pImmutableSamplers = desc[i].samplers; + desc_binding[i].pImmutableSamplers = desc[i].sampler ? + desc[i].sampler->sampler : + NULL; } desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; desc_create_layout.pBindings = desc_binding; desc_create_layout.bindingCount = num; - ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, - s->hwctx->alloc, layout); - av_free(desc_binding); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " - "layout: %s\n", ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; + for (int i = 0; i < pl->qf->nb_queues; i++) { + ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, + s->hwctx->alloc, &layout[i]); + if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " + "layout: %s\n", ff_vk_ret2str(ret)); + av_free(desc_binding); + return AVERROR_EXTERNAL; + } } + + av_free(desc_binding); } { /* Pool each descriptor by type and update pool counts */ @@ -1108,7 +1158,7 @@ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize)); } pl->pool_size_desc[j].type = desc[i].type; - pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1); + pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1)*pl->qf->nb_queues; } } @@ -1132,27 +1182,32 @@ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, pl->desc_template_info = av_realloc_array(pl->desc_template_info, sizeof(*pl->desc_template_info), - pl->desc_layout_num + 1); + pl->total_descriptor_sets + pl->qf->nb_queues); if (!pl->desc_template_info) return AVERROR(ENOMEM); - dt = &pl->desc_template_info[pl->desc_layout_num]; - memset(dt, 0, sizeof(*dt)); + dt = &pl->desc_template_info[pl->total_descriptor_sets]; + memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues); - dt->sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; - dt->templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; - dt->descriptorSetLayout = *layout; - dt->pDescriptorUpdateEntries = des_entries; - dt->descriptorUpdateEntryCount = num; + for (int i = 0; i < pl->qf->nb_queues; i++) { + dt[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; + dt[i].templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + dt[i].descriptorSetLayout = layout[i]; + dt[i].pDescriptorUpdateEntries = des_entries; + dt[i].descriptorUpdateEntryCount = num; + } } - pl->desc_layout_num++; + pl->descriptor_sets_num++; + + pl->desc_layout_num += pl->qf->nb_queues; + pl->total_descriptor_sets += pl->qf->nb_queues; print: /* Write shader info */ for (int i = 0; i < num; i++) { const struct descriptor_props *prop = &descriptor_props[desc[i].type]; - GLSLA("layout (set = %i, binding = %i", pl->desc_layout_num - 1, i); + GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i); if (desc[i].mem_layout) GLSLA(", %s", desc[i].mem_layout); @@ -1184,12 +1239,14 @@ print: return 0; } -void ff_vk_update_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, +void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, int set_id) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; + set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue; + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, pl->desc_set[set_id], pl->desc_template[set_id], @@ -1200,27 +1257,29 @@ void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, VkShaderStageFlagBits stage, int offset, size_t size, void *src) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - vk->CmdPushConstants(e->bufs[s->cur_queue_idx], e->bound_pl->pipeline_layout, + vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout, stage, offset, size, src); } -int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) +int ff_vk_init_pipeline_layout(AVFilterContext *avctx, FFVulkanPipeline *pl) { VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - pl->descriptor_sets_num = pl->desc_layout_num * s->queue_count; + pl->desc_staging = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_staging)); + if (!pl->desc_staging) + return AVERROR(ENOMEM); { /* Init descriptor set pool */ VkDescriptorPoolCreateInfo pool_create_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .poolSizeCount = pl->pool_size_desc_num, .pPoolSizes = pl->pool_size_desc, - .maxSets = pl->descriptor_sets_num, + .maxSets = pl->total_descriptor_sets, }; ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, @@ -1237,11 +1296,11 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) VkDescriptorSetAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .descriptorPool = pl->desc_pool, - .descriptorSetCount = pl->descriptor_sets_num, + .descriptorSetCount = pl->total_descriptor_sets, .pSetLayouts = pl->desc_layout, }; - pl->desc_set = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_set)); + pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set)); if (!pl->desc_set) return AVERROR(ENOMEM); @@ -1257,12 +1316,14 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) { /* Finally create the pipeline layout */ VkPipelineLayoutCreateInfo spawn_pipeline_layout = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = pl->desc_layout_num, - .pSetLayouts = pl->desc_layout, + .pSetLayouts = (VkDescriptorSetLayout *)pl->desc_staging, .pushConstantRangeCount = pl->push_consts_num, .pPushConstantRanges = pl->push_consts, }; + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) + pl->desc_staging[spawn_pipeline_layout.setLayoutCount++] = pl->desc_layout[i]; + ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, s->hwctx->alloc, &pl->pipeline_layout); av_freep(&pl->push_consts); @@ -1275,21 +1336,19 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) } { /* Descriptor template (for tightly packed descriptors) */ - VkDescriptorUpdateTemplateCreateInfo *desc_template_info; + VkDescriptorUpdateTemplateCreateInfo *dt; - pl->desc_template = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_template)); + pl->desc_template = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_template)); if (!pl->desc_template) return AVERROR(ENOMEM); /* Create update templates for the descriptor sets */ - for (int i = 0; i < pl->descriptor_sets_num; i++) { - desc_template_info = &pl->desc_template_info[i % pl->desc_layout_num]; - desc_template_info->pipelineLayout = pl->pipeline_layout; + for (int i = 0; i < pl->total_descriptor_sets; i++) { + dt = &pl->desc_template_info[i]; + dt->pipelineLayout = pl->pipeline_layout; ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev, - desc_template_info, - s->hwctx->alloc, + dt, s->hwctx->alloc, &pl->desc_template[i]); - av_free((void *)desc_template_info->pDescriptorUpdateEntries); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor " "template: %s\n", ff_vk_ret2str(ret)); @@ -1297,23 +1356,34 @@ int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) } } + /* Free the duplicated memory used for the template entries */ + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { + dt = &pl->desc_template_info[i]; + av_free((void *)dt->pDescriptorUpdateEntries); + } + av_freep(&pl->desc_template_info); } return 0; } -FN_CREATING(VulkanFilterContext, VulkanPipeline, pipeline, pipelines, pipelines_num) -VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx) +FN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num) +FFVulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx, + FFVkQueueFamilyCtx *qf) { - return create_pipeline(avctx->priv); + FFVulkanPipeline *pl = create_pipeline(avctx->priv); + if (pl) + pl->qf = qf; + + return pl; } -int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl) +int ff_vk_init_compute_pipeline(AVFilterContext *avctx, FFVulkanPipeline *pl) { int i; VkResult ret; - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkComputePipelineCreateInfo pipe = { @@ -1346,26 +1416,31 @@ int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl) } void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, - VulkanPipeline *pl) + FFVulkanPipeline *pl) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - vk->CmdBindPipeline(e->bufs[s->cur_queue_idx], pl->bind_point, pl->pipeline); + vk->CmdBindPipeline(e->bufs[e->qf->cur_queue], pl->bind_point, pl->pipeline); - vk->CmdBindDescriptorSets(e->bufs[s->cur_queue_idx], pl->bind_point, - pl->pipeline_layout, 0, pl->descriptor_sets_num, - pl->desc_set, 0, 0); + for (int i = 0; i < pl->descriptor_sets_num; i++) + pl->desc_staging[i] = pl->desc_set[i*pl->qf->nb_queues + pl->qf->cur_queue]; + + vk->CmdBindDescriptorSets(e->bufs[e->qf->cur_queue], pl->bind_point, + pl->pipeline_layout, 0, + pl->descriptor_sets_num, + (VkDescriptorSet *)pl->desc_staging, + 0, NULL); e->bound_pl = pl; } -static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) +static void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) { FFVulkanFunctions *vk = &s->vkfn; /* Make sure all queues have finished executing */ - for (int i = 0; i < s->queue_count; i++) { + for (int i = 0; i < e->qf->nb_queues; i++) { FFVkQueueCtx *q = &e->queues[i]; if (q->fence) { @@ -1389,7 +1464,7 @@ static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) } if (e->bufs) - vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, s->queue_count, e->bufs); + vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, e->qf->nb_queues, e->bufs); if (e->pool) vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); @@ -1397,13 +1472,14 @@ static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) av_freep(&e->queues); av_freep(&e->sem_sig); av_freep(&e->sem_sig_val); + av_freep(&e->sem_sig_val_dst); av_freep(&e->sem_wait); av_freep(&e->sem_wait_dst); av_freep(&e->sem_wait_val); av_free(e); } -static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) +static void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) { FFVulkanFunctions *vk = &s->vkfn; @@ -1433,6 +1509,7 @@ static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, s->hwctx->alloc); + av_freep(&pl->desc_staging); av_freep(&pl->desc_set); av_freep(&pl->shaders); av_freep(&pl->desc_layout); @@ -1443,8 +1520,10 @@ static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) /* Only freed in case of failure */ av_freep(&pl->pool_size_desc); if (pl->desc_template_info) { - for (int i = 0; i < pl->descriptor_sets_num; i++) - av_free((void *)pl->desc_template_info[i].pDescriptorUpdateEntries); + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { + VkDescriptorUpdateTemplateCreateInfo *dt = &pl->desc_template_info[i]; + av_free((void *)dt->pDescriptorUpdateEntries); + } av_freep(&pl->desc_template_info); } @@ -1453,7 +1532,7 @@ static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) void ff_vk_filter_uninit(AVFilterContext *avctx) { - VulkanFilterContext *s = avctx->priv; + FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; ff_vk_glslang_uninit(); @@ -1463,7 +1542,8 @@ void ff_vk_filter_uninit(AVFilterContext *avctx) av_freep(&s->exec_ctx); for (int i = 0; i < s->samplers_num; i++) { - vk->DestroySampler(s->hwctx->act_dev, *s->samplers[i], s->hwctx->alloc); + vk->DestroySampler(s->hwctx->act_dev, s->samplers[i]->sampler[0], + s->hwctx->alloc); av_free(s->samplers[i]); } av_freep(&s->samplers); diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index 89b76ba355..9d17d2b14f 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -20,6 +20,7 @@ #define AVFILTER_VULKAN_H #define VK_NO_PROTOTYPES +#define VK_ENABLE_BETA_EXTENSIONS #include "avfilter.h" #include "libavutil/pixdesc.h" @@ -52,9 +53,6 @@ goto fail; \ } while (0) -/* Useful for attaching immutable samplers to arrays */ -#define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, } - typedef struct FFSPIRVShader { const char *name; /* Name for id/debugging purposes */ AVBPrint src; @@ -62,7 +60,11 @@ typedef struct FFSPIRVShader { VkPipelineShaderStageCreateInfo shader; } FFSPIRVShader; -typedef struct VulkanDescriptorSetBinding { +typedef struct FFVkSampler { + VkSampler sampler[4]; +} FFVkSampler; + +typedef struct FFVulkanDescriptorSetBinding { const char *name; VkDescriptorType type; const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */ @@ -71,9 +73,9 @@ typedef struct VulkanDescriptorSetBinding { uint32_t dimensions; /* Needed for e.g. sampler%iD */ uint32_t elems; /* 0 - scalar, 1 or more - vector */ VkShaderStageFlags stages; - const VkSampler *samplers; /* Immutable samplers, length - #elems */ + FFVkSampler *sampler; /* Sampler to use for all elems */ void *updater; /* Pointer to VkDescriptor*Info */ -} VulkanDescriptorSetBinding; +} FFVulkanDescriptorSetBinding; typedef struct FFVkBuffer { VkBuffer buf; @@ -81,7 +83,15 @@ typedef struct FFVkBuffer { VkMemoryPropertyFlagBits flags; } FFVkBuffer; -typedef struct VulkanPipeline { +typedef struct FFVkQueueFamilyCtx { + int queue_family; + int nb_queues; + int cur_queue; +} FFVkQueueFamilyCtx; + +typedef struct FFVulkanPipeline { + FFVkQueueFamilyCtx *qf; + VkPipelineBindPoint bind_point; /* Contexts */ @@ -97,18 +107,21 @@ typedef struct VulkanPipeline { int push_consts_num; /* Descriptors */ - VkDescriptorSetLayout *desc_layout; - VkDescriptorPool desc_pool; - VkDescriptorSet *desc_set; - VkDescriptorUpdateTemplate *desc_template; - int desc_layout_num; - int descriptor_sets_num; - int pool_size_desc_num; + VkDescriptorSetLayout *desc_layout; + VkDescriptorPool desc_pool; + VkDescriptorSet *desc_set; + void **desc_staging; + VkDescriptorSetLayoutBinding **desc_binding; + VkDescriptorUpdateTemplate *desc_template; + int desc_layout_num; + int descriptor_sets_num; + int total_descriptor_sets; + int pool_size_desc_num; /* Temporary, used to store data in between initialization stages */ VkDescriptorUpdateTemplateCreateInfo *desc_template_info; VkDescriptorPoolSize *pool_size_desc; -} VulkanPipeline; +} FFVulkanPipeline; typedef struct FFVkQueueCtx { VkFence fence; @@ -126,6 +139,8 @@ typedef struct FFVkQueueCtx { } FFVkQueueCtx; typedef struct FFVkExecContext { + FFVkQueueFamilyCtx *qf; + VkCommandPool pool; VkCommandBuffer *bufs; FFVkQueueCtx *queues; @@ -134,7 +149,7 @@ typedef struct FFVkExecContext { int *nb_deps; int *dep_alloc_size; - VulkanPipeline *bound_pl; + FFVulkanPipeline *bound_pl; VkSemaphore *sem_wait; int sem_wait_alloc; /* Allocated sem_wait */ @@ -152,23 +167,23 @@ typedef struct FFVkExecContext { uint64_t *sem_sig_val; int sem_sig_val_alloc; + + uint64_t **sem_sig_val_dst; + int sem_sig_val_dst_alloc; } FFVkExecContext; -typedef struct VulkanFilterContext { +typedef struct FFVulkanContext { const AVClass *class; FFVulkanFunctions vkfn; FFVulkanExtensions extensions; + VkPhysicalDeviceProperties props; + VkPhysicalDeviceMemoryProperties mprops; AVBufferRef *device_ref; AVBufferRef *frames_ref; /* For in-place filtering */ AVHWDeviceContext *device; AVVulkanDeviceContext *hwctx; - /* State - mirrored with the exec ctx */ - int cur_queue_idx; - int queue_family_idx; - int queue_count; - /* Properties */ int output_width; int output_height; @@ -176,7 +191,7 @@ typedef struct VulkanFilterContext { enum AVPixelFormat input_format; /* Samplers */ - VkSampler **samplers; + FFVkSampler **samplers; int samplers_num; /* Exec contexts */ @@ -184,12 +199,12 @@ typedef struct VulkanFilterContext { int exec_ctx_num; /* Pipelines (each can have 1 shader of each type) */ - VulkanPipeline **pipelines; + FFVulkanPipeline **pipelines; int pipelines_num; void *scratch; /* Scratch memory used only in functions */ unsigned int scratch_size; -} VulkanFilterContext; +} FFVulkanContext; /* Identity mapping - r = r, b = b, g = g, a = a */ extern const VkComponentMapping ff_comp_identity_map; @@ -218,11 +233,23 @@ int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); */ const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); +/** + * Initialize a queue family. + * A queue limit of 0 means no limit. + */ +void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int queue_limit); + +/** + * Rotate through the queues in a queue family. + */ +void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf); + /** * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() */ -VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, - VkFilter filt); +FFVkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, + VkFilter filt); /** * Create an imageview. @@ -237,19 +264,20 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, * Define a push constant for a given stage into a pipeline. * Must be called before the pipeline layout has been initialized. */ -int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl, +int ff_vk_add_push_constant(AVFilterContext *avctx, FFVulkanPipeline *pl, int offset, int size, VkShaderStageFlagBits stage); /** * Inits a pipeline. Everything in it will be auto-freed when calling * ff_vk_filter_uninit(). */ -VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx); +FFVulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx, + FFVkQueueFamilyCtx *qf); /** * Inits a shader for a specific pipeline. Will be auto-freed on uninit. */ -FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, +FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, FFVulkanPipeline *pl, const char *name, VkShaderStageFlags stage); /** @@ -261,8 +289,8 @@ void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, /** * Adds a descriptor set to the shader and registers them in the pipeline. */ -int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - FFSPIRVShader *shd, VulkanDescriptorSetBinding *desc, +int ff_vk_add_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, + FFSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, int num, int only_print_to_shader); /** @@ -280,27 +308,28 @@ void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio); * Initializes the pipeline layout after all shaders and descriptor sets have * been finished. */ -int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl); +int ff_vk_init_pipeline_layout(AVFilterContext *avctx, FFVulkanPipeline *pl); /** * Initializes a compute pipeline. Will pick the first shader with the * COMPUTE flag set. */ -int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl); +int ff_vk_init_compute_pipeline(AVFilterContext *avctx, FFVulkanPipeline *pl); /** * Updates a descriptor set via the updaters defined. * Can be called immediately after pipeline creation, but must be called * at least once before queue submission. */ -void ff_vk_update_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, +void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, int set_id); /** * Init an execution context for command recording and queue submission. * WIll be auto-freed on uninit. */ -int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx); +int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx, + FFVkQueueFamilyCtx *qf); /** * Begin recording to the command buffer. Previous execution must have been @@ -313,7 +342,7 @@ int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e); * Must be called after ff_vk_start_exec_recording() and before submission. */ void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, - VulkanPipeline *pl); + FFVulkanPipeline *pl); /** * Updates push constants. From 8478d60d5b501248eb74caaffe5daccb48b27316 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 10 Nov 2021 08:10:08 +0100 Subject: [PATCH 122/894] doc/APIchanges: update for Vulkan API changes --- doc/APIchanges | 4 ++++ libavutil/version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 99e185ee4e..efc61c0e3d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,10 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-11-10 - xxxxxxxxxx - lavu 59.8.100 - hwcontext_vulkan.h + Added AVFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, + nb_encode_queues, ,queue_family_decode_index, and nb_encode_queues, + 2021-10-18 - xxxxxxxxxx - lavf 59.8.100 - avio.h Introduce public bytes_{read,written} statistic fields to AVIOContext. diff --git a/libavutil/version.h b/libavutil/version.h index 896e348d80..eeb33b388c 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 7 +#define LIBAVUTIL_VERSION_MINOR 8 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 511096c3a00b31bd5dfc540b9b56e64e2f85317d Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 12 Nov 2021 07:51:12 +0100 Subject: [PATCH 123/894] doc/APIchanges: fix typos and correct a date --- doc/APIchanges | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index efc61c0e3d..10bad1d21e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,9 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: -2021-11-10 - xxxxxxxxxx - lavu 59.8.100 - hwcontext_vulkan.h +2021-11-12 - xxxxxxxxxx - lavu 57.8.100 - hwcontext_vulkan.h Added AVFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, - nb_encode_queues, ,queue_family_decode_index, and nb_encode_queues, + nb_encode_queues, queue_family_decode_index, and nb_decode_queues. 2021-10-18 - xxxxxxxxxx - lavf 59.8.100 - avio.h Introduce public bytes_{read,written} statistic fields to AVIOContext. From ec6187b05be51f93af303db3f4364010fe16fee0 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 6 Nov 2021 22:38:08 +0800 Subject: [PATCH 124/894] avfilter/src_movie: make the number of decode thread configurable Signed-off-by: Limin Wang --- doc/filters.texi | 3 +++ libavfilter/src_movie.c | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 06aa3594d5..6ab41706e5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -28356,6 +28356,9 @@ changed, so it will generate non monotonically increasing timestamps. Specifies the time difference between frames above which the point is considered a timestamp discontinuity which is removed by adjusting the later timestamps. + +@item dec_threads +Specifies the number of threads for decoding @end table It allows overlaying a second video on top of the main input of diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 573f363705..220a43cdd1 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -67,6 +67,7 @@ typedef struct MovieContext { int loop_count; int64_t discontinuity_threshold; int64_t ts_offset; + int dec_threads; AVFormatContext *format_ctx; @@ -90,6 +91,7 @@ static const AVOption movie_options[]= { { "s", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, FLAGS }, { "loop", "set loop count", OFFSET(loop_count), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, FLAGS }, { "discontinuity", "set discontinuity threshold", OFFSET(discontinuity_threshold), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS }, + { "dec_threads", "set the number of threads for decoding", OFFSET(dec_threads), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, { NULL }, }; @@ -150,7 +152,7 @@ static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec) return found; } -static int open_stream(AVFilterContext *ctx, MovieStream *st) +static int open_stream(AVFilterContext *ctx, MovieStream *st, int dec_threads) { const AVCodec *codec; int ret; @@ -169,7 +171,9 @@ static int open_stream(AVFilterContext *ctx, MovieStream *st) if (ret < 0) return ret; - st->codec_ctx->thread_count = ff_filter_get_nb_threads(ctx); + if (!dec_threads) + dec_threads = ff_filter_get_nb_threads(ctx); + st->codec_ctx->thread_count = dec_threads; if ((ret = avcodec_open2(st->codec_ctx, codec, NULL)) < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to open codec\n"); @@ -314,7 +318,7 @@ static av_cold int movie_common_init(AVFilterContext *ctx) if (ret < 0) return ret; } - ret = open_stream(ctx, &movie->st[i]); + ret = open_stream(ctx, &movie->st[i], movie->dec_threads); if (ret < 0) return ret; } From 57e11321ea378a57a909d817c2fcf2ebcaf8c123 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 12 Nov 2021 13:05:42 +0100 Subject: [PATCH 125/894] hwcontext_vulkan: use vkDeviceWaitIdle instead of vkWaitSemaphores on uninit To silence a possible validation layer bug, switch the function. It only gets triggered by vf_libplacebo, which is odd. --- libavutil/hwcontext_vulkan.c | 12 +++--------- libavutil/vulkan_functions.h | 1 + 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 93a304ca95..6e746d4aa4 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1589,15 +1589,9 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) FFVulkanFunctions *vk = &p->vkfn; int planes = av_pix_fmt_count_planes(hwfc->sw_format); - VkSemaphoreWaitInfo wait_info = { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, - .flags = 0x0, - .pSemaphores = f->sem, - .pValues = f->sem_value, - .semaphoreCount = planes, - }; - - vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + /* We could use vkWaitSemaphores, but the validation layer seems to have + * issues tracking command buffer execution state on uninit. */ + vk->DeviceWaitIdle(hwctx->act_dev); vulkan_free_internal(f->internal); diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index de2054e0c2..913667befb 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -47,6 +47,7 @@ typedef enum FFVulkanExtensions { MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDevice) \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DeviceWaitIdle) \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDevice) \ \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumeratePhysicalDevices) \ From 296cb99d46b5f72d393ec06bef2753098d19fad2 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 12 Nov 2021 14:36:20 +0100 Subject: [PATCH 126/894] hwcontext_vulkan: fix CreateSemaphore conflict with synchapi.h Include windows.h to fix it. Normally, it'd be better to include it in vulkan_functions.h, but I'm reasonably confident nothing else that uses the Vulkan code will need to include Windows functions and not windows.h. --- libavutil/hwcontext_vulkan.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 6e746d4aa4..3c86e2d683 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -19,6 +19,13 @@ #define VK_NO_PROTOTYPES #define VK_ENABLE_BETA_EXTENSIONS +#ifdef _WIN32 +#include /* Included to prevent conflicts with CreateSemaphore */ +#include "compat/w32dlfcn.h" +#else +#include +#endif + #include #include "config.h" @@ -32,12 +39,6 @@ #include "vulkan_loader.h" -#ifdef _WIN32 -#include "compat/w32dlfcn.h" -#else -#include -#endif - #if CONFIG_LIBDRM #include #include From 51e03409d74f3eb265cd4e562819daffb3645cb0 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 26 Jul 2021 00:55:37 +0200 Subject: [PATCH 127/894] lavfi: add a libplacebo filter This filter conceptually maps the libplacebo `pl_renderer` API into libavfilter, which is a high-level image rendering API designed to work with an RGB pipeline internally. As such, there's no way to avoid e.g. chroma interpolation with this filter, although new versions of libplacebo support outputting back to subsampled YCbCr after processing is done. That being said, `pl_renderer` supports automatic integration of the majority of libplacebo's shaders, ranging from debanding to tone mapping, and also supports loading custom mpv-style user shaders, making this API a natural candidate for getting a lot of functionality out of relatively little code. In the future, I may approach this problem either by rewriting this filter to also support a non-renderer codepath, or by upgrading libplacebo's renderer to support a full YCbCr pipeline. This unfortunately requires a very new version of libplacebo (unreleased at time of writing) for timeline semaphore support. But the amount of boilerplate needed to hack in backwards compatibility would have been very unreasonable. --- configure | 3 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_libplacebo.c | 717 ++++++++++++++++++++++++++++++++++++ 4 files changed, 722 insertions(+) create mode 100644 libavfilter/vf_libplacebo.c diff --git a/configure b/configure index eb451d2782..891824757b 100755 --- a/configure +++ b/configure @@ -1827,6 +1827,7 @@ EXTERNAL_LIBRARY_LIST=" libopenmpt libopenvino libopus + libplacebo libpulse librabbitmq librav1e @@ -3618,6 +3619,7 @@ interlace_filter_deps="gpl" kerndeint_filter_deps="gpl" ladspa_filter_deps="ladspa libdl" lensfun_filter_deps="liblensfun version3" +libplacebo_filter_deps="libplacebo vulkan libglslang" lv2_filter_deps="lv2" mcdeint_filter_deps="avcodec gpl" metadata_filter_deps="avformat" @@ -6493,6 +6495,7 @@ enabled libopus && { require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create } } +enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.173.0" libplacebo/vulkan.h pl_vulkan_create enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection enabled librav1e && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 552bd4e286..e2059766b0 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -323,6 +323,7 @@ OBJS-$(CONFIG_LAGFUN_FILTER) += vf_lagfun.o OBJS-$(CONFIG_LATENCY_FILTER) += f_latency.o OBJS-$(CONFIG_LENSCORRECTION_FILTER) += vf_lenscorrection.o OBJS-$(CONFIG_LENSFUN_FILTER) += vf_lensfun.o +OBJS-$(CONFIG_LIBPLACEBO_FILTER) += vf_libplacebo.o vulkan.o OBJS-$(CONFIG_LIBVMAF_FILTER) += vf_libvmaf.o framesync.o OBJS-$(CONFIG_LIMITDIFF_FILTER) += vf_limitdiff.o framesync.o OBJS-$(CONFIG_LIMITER_FILTER) += vf_limiter.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 667b6fc246..be94249024 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -308,6 +308,7 @@ extern const AVFilter ff_vf_lagfun; extern const AVFilter ff_vf_latency; extern const AVFilter ff_vf_lenscorrection; extern const AVFilter ff_vf_lensfun; +extern const AVFilter ff_vf_libplacebo; extern const AVFilter ff_vf_libvmaf; extern const AVFilter ff_vf_limitdiff; extern const AVFilter ff_vf_limiter; diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c new file mode 100644 index 0000000000..0590e99093 --- /dev/null +++ b/libavfilter/vf_libplacebo.c @@ -0,0 +1,717 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/file.h" +#include "libavutil/opt.h" +#include "internal.h" +#include "vulkan.h" +#include "scale_eval.h" + +#include +#include +#include + +typedef struct LibplaceboContext { + /* lavfi vulkan*/ + FFVulkanContext vkctx; + int initialized; + + /* libplacebo */ + pl_log log; + pl_vulkan vulkan; + pl_gpu gpu; + pl_renderer renderer; + + /* settings */ + char *out_format_string; + char *w_expr; + char *h_expr; + AVRational target_sar; + float pad_crop_ratio; + int force_original_aspect_ratio; + int force_divisible_by; + int normalize_sar; + int apply_filmgrain; + int colorspace; + int color_range; + int color_primaries; + int color_trc; + + /* pl_render_params */ + char *upscaler; + char *downscaler; + int lut_entries; + float antiringing; + int sigmoid; + int skip_aa; + float polar_cutoff; + int disable_linear; + int disable_builtin; + int force_3dlut; + int force_dither; + int disable_fbos; + + /* pl_deband_params */ + int deband; + int deband_iterations; + float deband_threshold; + float deband_radius; + float deband_grain; + + /* pl_color_adjustment */ + float brightness; + float contrast; + float saturation; + float hue; + float gamma; + + /* pl_peak_detect_params */ + int peakdetect; + float smoothing; + float min_peak; + float scene_low; + float scene_high; + float overshoot; + + /* pl_color_map_params */ + int intent; + int tonemapping; + float tonemapping_param; + float desat_str; + float desat_exp; + float desat_base; + float max_boost; + int gamut_warning; + int gamut_clipping; + + /* pl_dither_params */ + int dithering; + int dither_lut_size; + int dither_temporal; + + /* pl_cone_params */ + int cones; + float cone_str; + + /* custom shaders */ + char *shader_path; + void *shader_bin; + int shader_bin_len; + const struct pl_hook *hooks[2]; + int num_hooks; +} LibplaceboContext; + +static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg) +{ + int av_lev; + + switch (level) { + case PL_LOG_FATAL: av_lev = AV_LOG_FATAL; break; + case PL_LOG_ERR: av_lev = AV_LOG_ERROR; break; + case PL_LOG_WARN: av_lev = AV_LOG_WARNING; break; + case PL_LOG_INFO: av_lev = AV_LOG_VERBOSE; break; + case PL_LOG_DEBUG: av_lev = AV_LOG_DEBUG; break; + case PL_LOG_TRACE: av_lev = AV_LOG_TRACE; break; + default: return; + } + + av_log(log_ctx, av_lev, "%s\n", msg); +} + +static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) +{ + LibplaceboContext *s = avctx->priv; + const struct pl_hook *hook; + + hook = pl_mpv_user_shader_parse(s->gpu, shader, len); + if (!hook) { + av_log(s, AV_LOG_ERROR, "Failed parsing custom shader!\n"); + return AVERROR(EINVAL); + } + + s->hooks[s->num_hooks++] = hook; + return 0; +} + +static int find_scaler(AVFilterContext *avctx, + const struct pl_filter_config **opt, + const char *name) +{ + const struct pl_filter_preset *preset; + if (!strcmp(name, "help")) { + av_log(avctx, AV_LOG_INFO, "Available scaler presets:\n"); + for (preset = pl_scale_filters; preset->name; preset++) + av_log(avctx, AV_LOG_INFO, " %s\n", preset->name); + return AVERROR_EXIT; + } + + for (preset = pl_scale_filters; preset->name; preset++) { + if (!strcmp(name, preset->name)) { + *opt = preset->filter; + return 0; + } + } + + av_log(avctx, AV_LOG_ERROR, "No such scaler preset '%s'.\n", name); + return AVERROR(EINVAL); +} + +static int libplacebo_init(AVFilterContext *avctx) +{ + LibplaceboContext *s = avctx->priv; + + /* Create libplacebo log context */ + s->log = pl_log_create(PL_API_VER, pl_log_params( + .log_level = PL_LOG_DEBUG, + .log_cb = pl_av_log, + .log_priv = s, + )); + + if (!s->log) + return AVERROR(ENOMEM); + + /* Note: s->vulkan etc. are initialized later, when hwctx is available */ + return 0; +} + +static int init_vulkan(AVFilterContext *avctx) +{ + int err = 0; + LibplaceboContext *s = avctx->priv; + const AVVulkanDeviceContext *hwctx = s->vkctx.hwctx; + uint8_t *buf = NULL; + size_t buf_len; + + /* Import libavfilter vulkan context into libplacebo */ + s->vulkan = pl_vulkan_import(s->log, pl_vulkan_import_params( + .instance = hwctx->inst, + .get_proc_addr = hwctx->get_proc_addr, + .phys_device = hwctx->phys_dev, + .device = hwctx->act_dev, + .extensions = hwctx->enabled_dev_extensions, + .num_extensions = hwctx->nb_enabled_dev_extensions, + .features = &hwctx->device_features, + .queue_graphics = { + .index = hwctx->queue_family_index, + .count = hwctx->nb_graphics_queues, + }, + .queue_compute = { + .index = hwctx->queue_family_comp_index, + .count = hwctx->nb_comp_queues, + }, + .queue_transfer = { + .index = hwctx->queue_family_tx_index, + .count = hwctx->nb_tx_queues, + }, + /* This is the highest version created by hwcontext_vulkan.c */ + .max_api_version = VK_API_VERSION_1_2, + )); + + if (!s->vulkan) { + av_log(s, AV_LOG_ERROR, "Failed importing vulkan device to libplacebo!\n"); + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Create the renderer */ + s->gpu = s->vulkan->gpu; + s->renderer = pl_renderer_create(s->log, s->gpu); + + /* Parse the user shaders, if requested */ + if (s->shader_bin_len) + RET(parse_shader(avctx, s->shader_bin, s->shader_bin_len)); + + if (s->shader_path && s->shader_path[0]) { + RET(av_file_map(s->shader_path, &buf, &buf_len, 0, s)); + RET(parse_shader(avctx, buf, buf_len)); + } + + /* fall through */ +fail: + if (buf) + av_file_unmap(buf, buf_len); + s->initialized = 1; + return err; +} + +static void libplacebo_uninit(AVFilterContext *avctx) +{ + LibplaceboContext *s = avctx->priv; + + for (int i = 0; i < s->num_hooks; i++) + pl_mpv_user_shader_destroy(&s->hooks[i]); + pl_renderer_destroy(&s->renderer); + pl_vulkan_destroy(&s->vulkan); + pl_log_destroy(&s->log); + ff_vk_filter_uninit(avctx); + s->initialized = 0; + s->gpu = NULL; +} + +static int wrap_vkframe(pl_gpu gpu, const AVFrame *frame, int plane, pl_tex *tex) +{ + AVVkFrame *vkf = (AVVkFrame *) frame->data[0]; + const AVHWFramesContext *hwfc = (AVHWFramesContext *) frame->hw_frames_ctx->data; + const AVVulkanFramesContext *vkfc = hwfc->hwctx; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); + const VkFormat *vk_fmt = av_vkfmt_from_pixfmt(hwfc->sw_format); + const int chroma = plane == 1 || plane == 2; + + *tex = pl_vulkan_wrap(gpu, pl_vulkan_wrap_params( + .image = vkf->img[plane], + .format = vk_fmt[plane], + .width = AV_CEIL_RSHIFT(frame->width, chroma ? desc->log2_chroma_w : 0), + .height = AV_CEIL_RSHIFT(frame->height, chroma ? desc->log2_chroma_h : 0), + .usage = vkfc->usage, + )); + + if (!*tex) + return AVERROR(ENOMEM); + + pl_vulkan_release(gpu, *tex, vkf->layout[plane], (pl_vulkan_sem) { + .sem = vkf->sem[plane], + .value = vkf->sem_value[plane] + }); + return 0; +} + +static int unwrap_vkframe(pl_gpu gpu, AVFrame *frame, int plane, pl_tex *tex) +{ + AVVkFrame *vkf = (AVVkFrame *) frame->data[0]; + int ok = pl_vulkan_hold_raw(gpu, *tex, &vkf->layout[plane], + (pl_vulkan_sem) { vkf->sem[plane], vkf->sem_value[plane] + 1 }); + vkf->access[plane] = 0; + vkf->sem_value[plane] += !!ok; + return ok ? 0 : AVERROR_EXTERNAL; +} + +static void set_sample_depth(struct pl_frame *out_frame, const AVFrame *frame) +{ + const AVHWFramesContext *hwfc = (AVHWFramesContext *) frame->hw_frames_ctx->data; + pl_fmt fmt = out_frame->planes[0].texture->params.format; + struct pl_bit_encoding *bits = &out_frame->repr.bits; + bits->sample_depth = fmt->component_depth[0]; + + switch (hwfc->sw_format) { + case AV_PIX_FMT_P010: bits->bit_shift = 6; break; + default: break; + } +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) +{ + int err = 0; + LibplaceboContext *s = avctx->priv; + struct pl_render_params params; + struct pl_frame image, target; + pl_frame_from_avframe(&image, in); + pl_frame_from_avframe(&target, out); + + if (!s->apply_filmgrain) + image.film_grain.type = PL_FILM_GRAIN_NONE; + + if (s->target_sar.num) { + float aspect = pl_rect2df_aspect(&target.crop) * av_q2d(s->target_sar); + pl_rect2df_aspect_set(&target.crop, aspect, s->pad_crop_ratio); + } + + /* Update render params */ + params = (struct pl_render_params) { + PL_RENDER_DEFAULTS + .lut_entries = s->lut_entries, + .antiringing_strength = s->antiringing, + + .deband_params = !s->deband ? NULL : pl_deband_params( + .iterations = s->deband_iterations, + .threshold = s->deband_threshold, + .radius = s->deband_radius, + .grain = s->deband_grain, + ), + + .sigmoid_params = s->sigmoid ? &pl_sigmoid_default_params : NULL, + + .color_adjustment = &(struct pl_color_adjustment) { + .brightness = s->brightness, + .contrast = s->contrast, + .saturation = s->saturation, + .hue = s->hue, + .gamma = s->gamma, + }, + + .peak_detect_params = !s->peakdetect ? NULL : pl_peak_detect_params( + .smoothing_period = s->smoothing, + .minimum_peak = s->min_peak, + .scene_threshold_low = s->scene_low, + .scene_threshold_high = s->scene_high, + .overshoot_margin = s->overshoot, + ), + + .color_map_params = pl_color_map_params( + .intent = s->intent, + .tone_mapping_algo = s->tonemapping, + .tone_mapping_param = s->tonemapping_param, + .desaturation_strength = s->desat_str, + .desaturation_exponent = s->desat_exp, + .desaturation_base = s->desat_base, + .max_boost = s->max_boost, + .gamut_warning = s->gamut_warning, + .gamut_clipping = s->gamut_clipping, + ), + + .dither_params = s->dithering < 0 ? NULL : pl_dither_params( + .method = s->dithering, + .lut_size = s->dither_lut_size, + .temporal = s->dither_temporal, + ), + + .cone_params = !s->cones ? NULL : pl_cone_params( + .cones = s->cones, + .strength = s->cone_str, + ), + + .hooks = s->hooks, + .num_hooks = s->num_hooks, + + .skip_anti_aliasing = s->skip_aa, + .polar_cutoff = s->polar_cutoff, + .disable_linear_scaling = s->disable_linear, + .disable_builtin_scalers = s->disable_builtin, + .force_3dlut = s->force_3dlut, + .force_dither = s->force_dither, + .disable_fbos = s->disable_fbos, + }; + + RET(find_scaler(avctx, ¶ms.upscaler, s->upscaler)); + RET(find_scaler(avctx, ¶ms.downscaler, s->downscaler)); + + /* Ideally, we would persistently wrap all of these AVVkFrames into pl_tex + * objects, but for now we'll just create and destroy a wrapper per frame. + * Note that doing it this way is suboptimal, since it results in the + * creation and destruction of a VkSampler and VkFramebuffer per frame. + * + * FIXME: Can we do better? */ + for (int i = 0; i < image.num_planes; i++) + RET(wrap_vkframe(s->gpu, in, i, &image.planes[i].texture)); + for (int i = 0; i < target.num_planes; i++) + RET(wrap_vkframe(s->gpu, out, i, &target.planes[i].texture)); + + /* Since we-re mapping vkframes manually, the pl_frame helpers don't know + * about the mismatch between the sample format and the color depth. */ + set_sample_depth(&image, in); + set_sample_depth(&target, out); + + pl_render_image(s->renderer, &image, &target, ¶ms); + + for (int i = 0; i < image.num_planes; i++) + RET(unwrap_vkframe(s->gpu, in, i, &image.planes[i].texture)); + for (int i = 0; i < target.num_planes; i++) + RET(unwrap_vkframe(s->gpu, out, i, &target.planes[i].texture)); + + /* Flush the command queues for performance */ + pl_gpu_flush(s->gpu); + + /* fall through */ +fail: + for (int i = 0; i < image.num_planes; i++) + pl_tex_destroy(s->gpu, &image.planes[i].texture); + for (int i = 0; i < target.num_planes; i++) + pl_tex_destroy(s->gpu, &target.planes[i].texture); + return err; +} + +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFilterContext *ctx = link->dst; + LibplaceboContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) + RET(init_vulkan(ctx)); + + RET(av_frame_copy_props(out, in)); + out->width = outlink->w; + out->height = outlink->h; + + if (s->colorspace >= 0) + out->colorspace = s->colorspace; + if (s->color_range >= 0) + out->color_range = s->color_range; + if (s->color_trc >= 0) + out->color_trc = s->color_trc; + if (s->color_primaries >= 0) + out->color_primaries = s->color_primaries; + + RET(process_frames(ctx, out, in)); + + if (s->apply_filmgrain) + av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static int libplacebo_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + LibplaceboContext *s = avctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + AVHWFramesContext *hwfc; + AVVulkanFramesContext *vkfc; + AVRational scale_sar; + int *out_w = &s->vkctx.output_width; + int *out_h = &s->vkctx.output_height; + + RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, + out_w, out_h)); + + ff_scale_adjust_dimensions(inlink, out_w, out_h, + s->force_original_aspect_ratio, + s->force_divisible_by); + + scale_sar = (AVRational){outlink->h * inlink->w, *out_w * *out_h}; + if (inlink->sample_aspect_ratio.num) + scale_sar = av_mul_q(scale_sar, inlink->sample_aspect_ratio); + + if (s->normalize_sar) { + /* Apply all SAR during scaling, so we don't need to set the out SAR */ + s->target_sar = scale_sar; + } else { + /* This is consistent with other scale_* filters, which only + * set the outlink SAR to be equal to the scale SAR iff the input SAR + * was set to something nonzero */ + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = scale_sar; + } + + if (s->out_format_string) { + s->vkctx.output_format = av_get_pix_fmt(s->out_format_string); + if (s->vkctx.output_format == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n"); + return AVERROR(EINVAL); + } + } else { + /* Default to re-using the input format */ + s->vkctx.output_format = s->vkctx.input_format; + } + + RET(ff_vk_filter_config_output(outlink)); + hwfc = (AVHWFramesContext *) outlink->hw_frames_ctx->data; + vkfc = hwfc->hwctx; + vkfc->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + return 0; + +fail: + return err; +} + +#define OFFSET(x) offsetof(LibplaceboContext, x) +#define STATIC (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +#define DYNAMIC (STATIC | AV_OPT_FLAG_RUNTIME_PARAM) + +static const AVOption libplacebo_options[] = { + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, + { "format", "Output video format", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = STATIC }, + { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, STATIC, "force_oar" }, + { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, STATIC, "force_oar" }, + { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, STATIC, "force_oar" }, + { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, STATIC, "force_oar" }, + { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, STATIC }, + { "normalize_sar", "force SAR normalization to 1:1", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, STATIC }, + { "pad_crop_ratio", "ratio between padding and cropping when normalizing SAR (0=pad, 1=crop)", OFFSET(pad_crop_ratio), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, 1.0, DYNAMIC }, + + {"colorspace", "select colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_NB-1, DYNAMIC, "colorspace"}, + {"auto", "keep the same colorspace", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"gbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_RGB}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT709}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE170M}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE240M}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"ycgco", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_YCGCO}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt2020nc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_NCL}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt2020c", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_CL}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"ictcp", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_ICTCP}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + + {"range", "select color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_RANGE_NB-1, DYNAMIC, "range"}, + {"auto", "keep the same color range", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, STATIC, "range"}, + {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, STATIC, "range"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, STATIC, "range"}, + {"limited", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, "range"}, + {"tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, "range"}, + {"mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, "range"}, + {"full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, "range"}, + {"pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, "range"}, + {"jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, "range"}, + + {"color_primaries", "select color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_PRI_NB-1, DYNAMIC, "color_primaries"}, + {"auto", "keep the same color primaries", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470M}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE240M}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"film", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_FILM}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE428}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + + {"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_NB-1, DYNAMIC, "color_trc"}, + {"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE170M}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE240M}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_LINEAR}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"iec61966-2-4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt1361e", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT1361_ECG}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"iec61966-2-1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt2020-10", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_10}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt2020-12", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + + { "upscaler", "Upscaler function", OFFSET(upscaler), AV_OPT_TYPE_STRING, {.str = "spline36"}, .flags = DYNAMIC }, + { "downscaler", "Downscaler function", OFFSET(downscaler), AV_OPT_TYPE_STRING, {.str = "mitchell"}, .flags = DYNAMIC }, + { "lut_entries", "Number of scaler LUT entries", OFFSET(lut_entries), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 256, DYNAMIC }, + { "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC }, + { "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "apply_filmgrain", "Apply film grain metadata", OFFSET(apply_filmgrain), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + + { "deband", "Enable debanding", OFFSET(deband), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "deband_iterations", "Deband iterations", OFFSET(deband_iterations), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 16, DYNAMIC }, + { "deband_threshold", "Deband threshold", OFFSET(deband_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 4.0}, 0.0, 1024.0, DYNAMIC }, + { "deband_radius", "Deband radius", OFFSET(deband_radius), AV_OPT_TYPE_FLOAT, {.dbl = 16.0}, 0.0, 1024.0, DYNAMIC }, + { "deband_grain", "Deband grain", OFFSET(deband_grain), AV_OPT_TYPE_FLOAT, {.dbl = 6.0}, 0.0, 1024.0, DYNAMIC }, + + { "brightness", "Brightness boost", OFFSET(brightness), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -1.0, 1.0, DYNAMIC }, + { "contrast", "Contrast gain", OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC }, + { "saturation", "Saturation gain", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC }, + { "hue", "Hue shift", OFFSET(hue), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -M_PI, M_PI, DYNAMIC }, + { "gamma", "Gamma adjustment", OFFSET(gamma), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC }, + + { "peak_detect", "Enable dynamic peak detection for HDR tone-mapping", OFFSET(peakdetect), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "smoothing_period", "Peak detection smoothing period", OFFSET(smoothing), AV_OPT_TYPE_FLOAT, {.dbl = 100.0}, 0.0, 1000.0, DYNAMIC }, + { "minimum_peak", "Peak detection minimum peak", OFFSET(min_peak), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 100.0, DYNAMIC }, + { "scene_threshold_low", "Scene change low threshold", OFFSET(scene_low), AV_OPT_TYPE_FLOAT, {.dbl = 5.5}, -1.0, 100.0, DYNAMIC }, + { "scene_threshold_high", "Scene change high threshold", OFFSET(scene_high), AV_OPT_TYPE_FLOAT, {.dbl = 10.0}, -1.0, 100.0, DYNAMIC }, + { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC }, + + { "intent", "Rendering intent", OFFSET(intent), AV_OPT_TYPE_INT, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 3, DYNAMIC, "intent" }, + { "perceptual", "Perceptual", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_PERCEPTUAL}, 0, 0, STATIC, "intent" }, + { "relative", "Relative colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, + { "absolute", "Absolute colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_ABSOLUTE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, + { "saturation", "Saturation mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_SATURATION}, 0, 0, STATIC, "intent" }, + { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = PL_TONE_MAPPING_BT_2390}, 0, PL_TONE_MAPPING_ALGORITHM_COUNT - 1, DYNAMIC, "tonemap" }, + { "clip", "Hard-clipping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_CLIP}, 0, 0, STATIC, "tonemap" }, + { "mobius", "Mobius tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_MOBIUS}, 0, 0, STATIC, "tonemap" }, + { "reinhard", "Reinhard tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_REINHARD}, 0, 0, STATIC, "tonemap" }, + { "hable", "Hable/Filmic tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_HABLE}, 0, 0, STATIC, "tonemap" }, + { "gamma", "Gamma tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_GAMMA}, 0, 0, STATIC, "tonemap" }, + { "linear", "Linear tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_LINEAR}, 0, 0, STATIC, "tonemap" }, + { "bt.2390", "ITU-R BT.2390 tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_BT_2390}, 0, 0, STATIC, "tonemap" }, + { "tonemapping_param", "Tunable parameter for some tone-mapping functions", OFFSET(tonemapping_param), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 100.0, .flags = DYNAMIC }, + { "desaturation_strength", "Desaturation strength", OFFSET(desat_str), AV_OPT_TYPE_FLOAT, {.dbl = 0.90}, 0.0, 1.0, DYNAMIC }, + { "desaturation_exponent", "Desaturation exponent", OFFSET(desat_exp), AV_OPT_TYPE_FLOAT, {.dbl = 0.2}, 0.0, 10.0, DYNAMIC }, + { "desaturation_base", "Desaturation base", OFFSET(desat_base), AV_OPT_TYPE_FLOAT, {.dbl = 0.18}, 0.0, 10.0, DYNAMIC }, + { "max_boost", "Tone-mapping maximum boost", OFFSET(max_boost), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 1.0, 10.0, DYNAMIC }, + { "gamut_warning", "Highlight out-of-gamut colors", OFFSET(gamut_warning), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "gamut_clipping", "Enable colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + + { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, + { "none", "Disable dithering", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, STATIC, "dither" }, + { "blue", "Blue noise", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_BLUE_NOISE}, 0, 0, STATIC, "dither" }, + { "ordered", "Ordered LUT", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_ORDERED_LUT}, 0, 0, STATIC, "dither" }, + { "ordered_fixed", "Fixed function ordered", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_ORDERED_FIXED}, 0, 0, STATIC, "dither" }, + { "white", "White noise", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_WHITE_NOISE}, 0, 0, STATIC, "dither" }, + { "dither_lut_size", "Dithering LUT size", OFFSET(dither_lut_size), AV_OPT_TYPE_INT, {.i64 = 6}, 1, 8, STATIC }, + { "dither_temporal", "Enable temporal dithering", OFFSET(dither_temporal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + + { "cones", "Colorblindness adaptation model", OFFSET(cones), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, PL_CONE_LMS, DYNAMIC, "cone" }, + { "l", "L cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_L}, 0, 0, STATIC, "cone" }, + { "m", "M cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_M}, 0, 0, STATIC, "cone" }, + { "s", "S cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_S}, 0, 0, STATIC, "cone" }, + { "cone-strength", "Colorblindness adaptation strength", OFFSET(cone_str), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 10.0, DYNAMIC }, + + { "custom_shader_path", "Path to custom user shader (mpv .hook format)", OFFSET(shader_path), AV_OPT_TYPE_STRING, .flags = STATIC }, + { "custom_shader_bin", "Custom user shader as binary (mpv .hook format)", OFFSET(shader_bin), AV_OPT_TYPE_BINARY, .flags = STATIC }, + + /* Performance/quality tradeoff options */ + { "skip_aa", "Skip anti-aliasing", OFFSET(skip_aa), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 0, DYNAMIC }, + { "polar_cutoff", "Polar LUT cutoff", OFFSET(polar_cutoff), AV_OPT_TYPE_FLOAT, {.i64 = 0}, 0.0, 1.0, DYNAMIC }, + { "disable_linear", "Disable linear scaling", OFFSET(disable_linear), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "disable_builtin", "Disable built-in scalers", OFFSET(disable_builtin), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "force_3dlut", "Force the use of a full 3DLUT", OFFSET(force_3dlut), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "force_dither", "Force dithering", OFFSET(force_dither), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "disable_fbos", "Force-disable FBOs", OFFSET(disable_fbos), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(libplacebo); + +static const AVFilterPad libplacebo_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &filter_frame, + .config_props = &ff_vk_filter_config_input, + }, +}; + +static const AVFilterPad libplacebo_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &libplacebo_config_output, + }, +}; + +AVFilter ff_vf_libplacebo = { + .name = "libplacebo", + .description = NULL_IF_CONFIG_SMALL("Apply various GPU filters from libplacebo"), + .priv_size = sizeof(LibplaceboContext), + .init = &libplacebo_init, + .uninit = &libplacebo_uninit, + .process_command = &ff_filter_process_command, + FILTER_INPUTS(libplacebo_inputs), + FILTER_OUTPUTS(libplacebo_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &libplacebo_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From a943f527a13d2d6afd38593a2dc1de69e6d0972c Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 12 Nov 2021 20:24:02 +0100 Subject: [PATCH 128/894] lavfi/vf_libplacebo: pick log level dynamically In particular, allows users to go all the way up to PL_LOG_TRACE if desired. (While also avoiding some potentially unnecessary callbacks for filtered messages, including e.g. the CPU cost of printing out shader sources) Response to runtime log level changes by updating it once per filter_frame(), which should hopefully be often enough. --- libavfilter/vf_libplacebo.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 0590e99093..ede6888bd3 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -116,6 +116,18 @@ typedef struct LibplaceboContext { int num_hooks; } LibplaceboContext; +static inline enum pl_log_level get_log_level(void) +{ + int av_lev = av_log_get_level(); + return av_lev >= AV_LOG_TRACE ? PL_LOG_TRACE : + av_lev >= AV_LOG_DEBUG ? PL_LOG_DEBUG : + av_lev >= AV_LOG_VERBOSE ? PL_LOG_INFO : + av_lev >= AV_LOG_WARNING ? PL_LOG_WARN : + av_lev >= AV_LOG_ERROR ? PL_LOG_ERR : + av_lev >= AV_LOG_FATAL ? PL_LOG_FATAL : + PL_LOG_NONE; +} + static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg) { int av_lev; @@ -177,7 +189,7 @@ static int libplacebo_init(AVFilterContext *avctx) /* Create libplacebo log context */ s->log = pl_log_create(PL_API_VER, pl_log_params( - .log_level = PL_LOG_DEBUG, + .log_level = get_log_level(), .log_cb = pl_av_log, .log_priv = s, )); @@ -447,6 +459,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) goto fail; } + pl_log_level_update(s->log, get_log_level()); if (!s->initialized) RET(init_vulkan(ctx)); From 8449baf9aac2ad86ddb21bb64a51b94010f354e3 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 12 Nov 2021 23:50:10 +0100 Subject: [PATCH 129/894] hwcontext_vulkan: properly error out if timeline semaphores are unsupported Missing goto. --- libavutil/hwcontext_vulkan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 3c86e2d683..2f72024617 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1215,6 +1215,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (!dev_features_1_2.timelineSemaphore) { av_log(ctx, AV_LOG_ERROR, "Device does not support timeline semaphores!\n"); err = AVERROR(ENOSYS); + goto end; } p->device_features_1_2.timelineSemaphore = 1; From 549d91ae3a13cff91caba75d2b795acc8f3e7513 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 12 Nov 2021 23:51:11 +0100 Subject: [PATCH 130/894] hwcontext_vulkan: properly migrate between queue families on CUDA import/export It's more correct. --- libavutil/hwcontext_vulkan.c | 93 ++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 2f72024617..f5c0c775e4 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1679,13 +1679,14 @@ enum PrepMode { PREP_MODE_WRITE, PREP_MODE_RO_SHADER, PREP_MODE_EXTERNAL_EXPORT, + PREP_MODE_EXTERNAL_IMPORT }; static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, AVVkFrame *frame, enum PrepMode pmode) { int err; - uint32_t dst_qf; + uint32_t src_qf, dst_qf; VkImageLayout new_layout; VkAccessFlags new_access; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); @@ -1718,16 +1719,30 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, case PREP_MODE_WRITE: new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; new_access = VK_ACCESS_TRANSFER_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; dst_qf = VK_QUEUE_FAMILY_IGNORED; break; case PREP_MODE_RO_SHADER: new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; new_access = VK_ACCESS_TRANSFER_READ_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; dst_qf = VK_QUEUE_FAMILY_IGNORED; break; + case PREP_MODE_EXTERNAL_IMPORT: + new_layout = VK_IMAGE_LAYOUT_GENERAL; + new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; + dst_qf = VK_QUEUE_FAMILY_IGNORED; + s_timeline_sem_info.pWaitSemaphoreValues = frame->sem_value; + s_timeline_sem_info.waitSemaphoreValueCount = planes; + s_info.pWaitSemaphores = frame->sem; + s_info.pWaitDstStageMask = wait_st; + s_info.waitSemaphoreCount = planes; + break; case PREP_MODE_EXTERNAL_EXPORT: new_layout = VK_IMAGE_LAYOUT_GENERAL; new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; s_timeline_sem_info.pWaitSemaphoreValues = frame->sem_value; s_timeline_sem_info.waitSemaphoreValueCount = planes; @@ -1749,7 +1764,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, img_bar[i].dstAccessMask = new_access; img_bar[i].oldLayout = frame->layout[i]; img_bar[i].newLayout = new_layout; - img_bar[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + img_bar[i].srcQueueFamilyIndex = src_qf; img_bar[i].dstQueueFamilyIndex = dst_qf; img_bar[i].image = frame->img[i]; img_bar[i].subresourceRange.levelCount = 1; @@ -2723,10 +2738,10 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src) { int err; - VkResult ret; CUcontext dummy; AVVkFrame *dst_f; AVVkFrameInternal *dst_int; + VulkanFramesPriv *fp = hwfc->internal->priv; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); @@ -2738,16 +2753,20 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 }; CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 }; - ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); - if (ret < 0) - return AVERROR_EXTERNAL; - dst_f = (AVVkFrame *)dst->data[0]; - ret = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst); - if (ret < 0) { + err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_EXPORT); + if (err < 0) + return err; + + err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); + if (err < 0) + return err; + + err = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst); + if (err < 0) { CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - return ret; + return err; } dst_int = dst_f->internal; @@ -2757,12 +2776,10 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1; } - ret = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, + err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + if (err < 0) goto fail; - } for (int i = 0; i < planes; i++) { CUDA_MEMCPY2D cpy = { @@ -2781,19 +2798,15 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, cpy.WidthInBytes = p_w * desc->comp[i].step; cpy.Height = p_h; - ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); + if (err < 0) goto fail; - } } - ret = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, + err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + if (err < 0) goto fail; - } for (int i = 0; i < planes; i++) dst_f->sem_value[i]++; @@ -2802,7 +2815,7 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, av_log(hwfc, AV_LOG_VERBOSE, "Transfered CUDA image to Vulkan!\n"); - return 0; + return err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_IMPORT); fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); @@ -3550,10 +3563,10 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src) { int err; - VkResult ret; CUcontext dummy; AVVkFrame *dst_f; AVVkFrameInternal *dst_int; + VulkanFramesPriv *fp = hwfc->internal->priv; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); @@ -3565,12 +3578,16 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 }; CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 }; - ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); - if (ret < 0) - return AVERROR_EXTERNAL; - dst_f = (AVVkFrame *)src->data[0]; + err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_EXPORT); + if (err < 0) + return err; + + err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); + if (err < 0) + return err; + err = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src); if (err < 0) { CHECK_CU(cu->cuCtxPopCurrent(&dummy)); @@ -3584,12 +3601,10 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1; } - ret = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, + err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + if (err < 0) goto fail; - } for (int i = 0; i < planes; i++) { CUDA_MEMCPY2D cpy = { @@ -3608,19 +3623,15 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, cpy.WidthInBytes = w * desc->comp[i].step; cpy.Height = h; - ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); + if (err < 0) goto fail; - } } - ret = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, + err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + if (err < 0) goto fail; - } for (int i = 0; i < planes; i++) dst_f->sem_value[i]++; @@ -3629,7 +3640,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, av_log(hwfc, AV_LOG_VERBOSE, "Transfered Vulkan image to CUDA!\n"); - return 0; + return prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_IMPORT); fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); From fa28c1b2f9d6fa9e3c0e89c27ad9a55add3a620f Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 12 Nov 2021 23:54:36 +0100 Subject: [PATCH 131/894] hwcontext_vulkan: properly migrate queue families with DRM import/export --- libavutil/hwcontext_vulkan.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f5c0c775e4..4ab8a3f6ad 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1677,7 +1677,6 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, enum PrepMode { PREP_MODE_WRITE, - PREP_MODE_RO_SHADER, PREP_MODE_EXTERNAL_EXPORT, PREP_MODE_EXTERNAL_IMPORT }; @@ -1722,12 +1721,6 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, src_qf = VK_QUEUE_FAMILY_IGNORED; dst_qf = VK_QUEUE_FAMILY_IGNORED; break; - case PREP_MODE_RO_SHADER: - new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - new_access = VK_ACCESS_TRANSFER_READ_BIT; - src_qf = VK_QUEUE_FAMILY_IGNORED; - dst_qf = VK_QUEUE_FAMILY_IGNORED; - break; case PREP_MODE_EXTERNAL_IMPORT: new_layout = VK_IMAGE_LAYOUT_GENERAL; new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; @@ -2504,10 +2497,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f goto fail; } - /* NOTE: This is completely uneccesary and unneeded once we can import - * semaphores from DRM. Otherwise we have to activate the semaphores. - * We're reusing the exec context that's also used for uploads/downloads. */ - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_RO_SHADER); + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_EXTERNAL_IMPORT); if (err) goto fail; From 015b487777cc3bd540f7d77e7ce902a3ab4a7239 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 00:14:10 +0100 Subject: [PATCH 132/894] hwcontext_vulkan: do not dup() semaphore FDs for CUDA --- libavutil/hwcontext_vulkan.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 4ab8a3f6ad..0dbbb9d12f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -123,7 +123,6 @@ typedef struct AVVkFrameInternal { CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS]; CUarray cu_array[AV_NUM_DATA_POINTERS]; CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS]; - int exp_sem[AV_NUM_DATA_POINTERS]; #endif } AVVkFrameInternal; @@ -1572,7 +1571,6 @@ static void vulkan_free_internal(AVVkFrameInternal *internal) CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i])); if (internal->ext_mem[i]) CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i])); - close(internal->exp_sem[i]); } av_buffer_unref(&internal->cuda_fc_ref); @@ -2698,7 +2696,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, } ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export, - &dst_int->exp_sem[i]); + &ext_sem_desc.handle.fd); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n", vk_ret2str(ret)); @@ -2706,8 +2704,6 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, goto fail; } - ext_sem_desc.handle.fd = dup(dst_int->exp_sem[i]); - ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[i], &ext_sem_desc)); if (ret < 0) { From 0d1992e0255ab5cdc026e9190f7b7a114bdeef74 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 00:40:46 +0100 Subject: [PATCH 133/894] hwcontext_vulkan: close exported memory FD on CUDA import error Prevents resource leakage. --- libavutil/hwcontext_vulkan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 0dbbb9d12f..c95c08ff52 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2676,6 +2676,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[i], &ext_desc)); if (ret < 0) { + close(ext_desc.handle.fd); err = AVERROR_EXTERNAL; goto fail; } From f74ceb358c3042a7d3c6b61fc0149d0caafd4158 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 04:14:04 +0100 Subject: [PATCH 134/894] hwcontext_vulkan: improve CUDA error handling --- libavutil/hwcontext_vulkan.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index c95c08ff52..c054d84a29 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1550,8 +1550,10 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, return 0; } -static void vulkan_free_internal(AVVkFrameInternal *internal) +static void vulkan_free_internal(AVVkFrame *f) { + AVVkFrameInternal *internal = f->internal; + if (!internal) return; @@ -1577,7 +1579,7 @@ static void vulkan_free_internal(AVVkFrameInternal *internal) } #endif - av_free(internal); + av_freep(&f->internal); } static void vulkan_frame_free(void *opaque, uint8_t *data) @@ -1593,7 +1595,7 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) * issues tracking command buffer execution state on uninit. */ vk->DeviceWaitIdle(hwctx->act_dev); - vulkan_free_internal(f->internal); + vulkan_free_internal(f); for (int i = 0; i < planes; i++) { vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); @@ -2620,15 +2622,13 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, if (!dst_f->internal) dst_f->internal = dst_int = av_mallocz(sizeof(*dst_f->internal)); - if (!dst_int) { - err = AVERROR(ENOMEM); - goto fail; - } + if (!dst_int) + return AVERROR(ENOMEM); dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc); if (!dst_int->cuda_fc_ref) { - err = AVERROR(ENOMEM); - goto fail; + av_freep(&dst_f->internal); + return AVERROR(ENOMEM); } for (int i = 0; i < planes; i++) { @@ -2669,7 +2669,8 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info, &ext_desc.handle.fd); if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD!\n"); + av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n", + vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } @@ -2718,6 +2719,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, return 0; fail: + vulkan_free_internal(dst_f); return err; } @@ -2806,7 +2808,7 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - vulkan_free_internal(dst_int); + vulkan_free_internal(dst_f); dst_f->internal = NULL; av_buffer_unref(&dst->buf[0]); return err; @@ -3631,7 +3633,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - vulkan_free_internal(dst_int); + vulkan_free_internal(dst_f); dst_f->internal = NULL; av_buffer_unref(&dst->buf[0]); return err; From c96d1ee401189188de881f6cd005f9ab45b65834 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 11:11:47 +0100 Subject: [PATCH 135/894] hwcontext_vulkan: fix DMABUF import format check call VkExternalImageFormatProperties is required to be present in the .pNext chain of VkImageFormatProperties2, or some drivers crash (RADV). --- libavutil/hwcontext_vulkan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index c054d84a29..fd9d4d481f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2329,8 +2329,12 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f }; /* Image format verification */ + VkExternalImageFormatProperties ext_props = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, + }; VkImageFormatProperties2 props_ret = { .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + .pNext = &ext_props, }; VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, From 6a23a5597cd77506210cb14265e94e012a942abd Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 14:21:36 +0100 Subject: [PATCH 136/894] hwcontext_vulkan: print error information on queue submission failure Makes it clearer what went wrong. --- libavutil/hwcontext_vulkan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index fd9d4d481f..31c7dc2aa5 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1108,6 +1108,8 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, ret = vk->QueueSubmit(q->queue, 1, s_info, q->fence); if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Queue submission failure: %s\n", + vk_ret2str(ret)); unref_exec_ctx_deps(hwfc, cmd); return AVERROR_EXTERNAL; } From 9dc544cdb461789f0d950c384464fcc893cd804c Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 14:22:11 +0100 Subject: [PATCH 137/894] hwcontext_vulkan: wait for semaphores when unmapping from VAAPI We don't really want to do a full all-queue blocking wait here, since this happens once per frame, and this could delay future frames. --- libavutil/hwcontext_vulkan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 31c7dc2aa5..e54c10156e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2218,6 +2218,16 @@ static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; + VkSemaphoreWaitInfo wait_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .flags = 0x0, + .pSemaphores = map->frame->sem, + .pValues = map->frame->sem_value, + .semaphoreCount = planes, + }; + + vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + for (int i = 0; i < planes; i++) { vk->DestroyImage(hwctx->act_dev, map->frame->img[i], hwctx->alloc); vk->FreeMemory(hwctx->act_dev, map->frame->mem[i], hwctx->alloc); From f388791ff99938396d622886e8ff760e0f398028 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 14:47:12 +0100 Subject: [PATCH 138/894] hwcontext_vulkan: fix small memory leak when unmapping --- libavutil/hwcontext_vulkan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index e54c10156e..7c70fac30f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2235,6 +2235,7 @@ static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) } av_freep(&map->frame); + av_free(map); } static const struct { From 7f6dc9b3868626f6d37ec747d84df973842d5d50 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 13 Nov 2021 15:13:03 +0100 Subject: [PATCH 139/894] hwcontext_vaapi: don't use the generic mapping struct for DRM/VAAPI Avoids a per-frame allocation since we don't need the flag field. --- libavutil/hwcontext_vulkan.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 7c70fac30f..d40b1e5de0 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2210,9 +2210,9 @@ fail: } #if CONFIG_LIBDRM -static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) +static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) { - VulkanMapping *map = hwmap->priv; + AVVkFrame *f = hwmap->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; @@ -2221,21 +2221,22 @@ static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) VkSemaphoreWaitInfo wait_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, .flags = 0x0, - .pSemaphores = map->frame->sem, - .pValues = map->frame->sem_value, + .pSemaphores = f->sem, + .pValues = f->sem_value, .semaphoreCount = planes, }; vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + vulkan_free_internal(f); + for (int i = 0; i < planes; i++) { - vk->DestroyImage(hwctx->act_dev, map->frame->img[i], hwctx->alloc); - vk->FreeMemory(hwctx->act_dev, map->frame->mem[i], hwctx->alloc); - vk->DestroySemaphore(hwctx->act_dev, map->frame->sem[i], hwctx->alloc); + vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); + vk->FreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc); + vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc); } - av_freep(&map->frame); - av_free(map); + av_free(f); } static const struct { @@ -2540,7 +2541,6 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, { int err = 0; AVVkFrame *f; - VulkanMapping *map = NULL; if ((err = vulkan_map_from_drm_frame_desc(hwfc, &f, src))) return err; @@ -2550,15 +2550,8 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; - map = av_mallocz(sizeof(VulkanMapping)); - if (!map) - goto fail; - - map->frame = f; - map->flags = flags; - err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, - &vulkan_unmap_from, map); + &vulkan_unmap_from_drm, f); if (err < 0) goto fail; @@ -2568,7 +2561,6 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, fail: vulkan_frame_free(hwfc->device_ctx->hwctx, (uint8_t *)f); - av_free(map); return err; } From 47451d9267caf8f989530d0d7a1311f6205a2c21 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 12 Nov 2021 13:02:34 -0300 Subject: [PATCH 140/894] avdevice/dshow: fix print format for some variables WAVEFORMATEX.nChannels and WAVEFORMATEX.wBitsPerSample are of type WORD, aka unsigned short. Signed-off-by: James Almer --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index e313c9a2bf..fd62d79443 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -425,7 +425,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, av_log( avctx, AV_LOG_INFO, - " ch=%2lu, bits=%2lu, rate=%6lu\n", + " ch=%2u, bits=%2u, rate=%6lu\n", fx->nChannels, fx->wBitsPerSample, fx->nSamplesPerSec ); continue; From b664df3ff47ab23a59bc5232249251f66f7115f9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 12 Nov 2021 13:03:58 -0300 Subject: [PATCH 141/894] avdevice/dshow: fix a unused variable warning Unused if DSHOWDEBUG is not set since commit d9a9b4c877b85fea5a5bad74c3d592a756047f79. Signed-off-by: James Almer --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index fd62d79443..ef78781865 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -411,9 +411,9 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, bih->biHeight = ctx->requested_height; } } else { - AUDIO_STREAM_CONFIG_CAPS *acaps = caps; WAVEFORMATEX *fx; #if DSHOWDEBUG + AUDIO_STREAM_CONFIG_CAPS *acaps = caps; ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps); #endif if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) { From fba4d6f72b27b0dce1774e8e1eee2245cad9ffd2 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Sat, 7 Aug 2021 05:02:11 +0000 Subject: [PATCH 142/894] avutil/hwcontext_dxva2: add ARGB format Required for uploading frames with alpha for qsv_overlay (v2: remove tab indent) Signed-off-by: softworkz Signed-off-by: Marton Balint --- libavutil/hwcontext_dxva2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index f3e578fc10..53d00fa815 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -83,6 +83,7 @@ static const struct { { MKTAG('N', 'V', '1', '2'), AV_PIX_FMT_NV12 }, { MKTAG('P', '0', '1', '0'), AV_PIX_FMT_P010 }, { D3DFMT_P8, AV_PIX_FMT_PAL8 }, + { D3DFMT_A8R8G8B8, AV_PIX_FMT_BGRA }, }; DEFINE_GUID(video_decoder_service, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02); From 89ba6e9a04d2852d5d042dfd2afde727d2f39bea Mon Sep 17 00:00:00 2001 From: Soft Works Date: Sat, 7 Aug 2021 20:29:16 +0000 Subject: [PATCH 143/894] doc/developer: add description about safely sending patches via E-Mail clients Signed-off-by: softworkz Signed-off-by: Marton Balint --- doc/developer.texi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/developer.texi b/doc/developer.texi index b33cab0fc7..addee0d826 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -494,6 +494,22 @@ patch is inline or attached per mail. You can check @url{https://patchwork.ffmpeg.org}, if your patch does not show up, its mime type likely was wrong. +@subheading Sending patches from email clients +Using @code{git send-email} might not be desirable for everyone. The +following trick allows to send patches via email clients in a safe +way. It has been tested with Outlook and Thunderbird (with X-Unsent +extension) and might work with other applications. + +Create your patch like this: + +@verbatim +git format-patch -s -o "outputfolder" --add-header "X-Unsent: 1" --suffix .eml --to ffmpeg-devel@ffmpeg.org -1 1a2b3c4d +@end verbatim + +Now you'll just need to open the eml file with the email application +and execute 'Send'. + +@subheading Reviews Your patch will be reviewed on the mailing list. You will likely be asked to make some changes and are expected to send in an improved version that incorporates the requests from the review. This process may go through From 0a99c8322a469ad54cce3c49bd9d1681f3ef6388 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Sun, 10 Oct 2021 17:01:43 +0000 Subject: [PATCH 144/894] fftools/ffmpeg: Remove redundant loop Signed-off-by: softworkz Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9d4f9d7a2b..e205945e63 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2178,7 +2178,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) { FilterGraph *fg = ifilter->graph; AVFrameSideData *sd; - int need_reinit, ret, i; + int need_reinit, ret; /* determine if the parameters for this input changed */ need_reinit = ifilter->format != frame->format; @@ -2216,7 +2216,6 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) /* (re)init the graph if possible, otherwise buffer the frame and return */ if (need_reinit || !fg->graph) { - for (i = 0; i < fg->nb_inputs; i++) { if (!ifilter_has_all_input_formats(fg)) { AVFrame *tmp = av_frame_clone(frame); if (!tmp) @@ -2233,7 +2232,6 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); return 0; } - } ret = reap_filters(1); if (ret < 0 && ret != AVERROR_EOF) { From bcbedd2749e570ea62399cb316b4ae18c6c6f802 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Sun, 10 Oct 2021 17:01:56 +0000 Subject: [PATCH 145/894] fftools/ffmpeg: Fix indentation after change Signed-off-by: softworkz Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e205945e63..7545b7c68e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2216,22 +2216,22 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) /* (re)init the graph if possible, otherwise buffer the frame and return */ if (need_reinit || !fg->graph) { - if (!ifilter_has_all_input_formats(fg)) { - AVFrame *tmp = av_frame_clone(frame); - if (!tmp) - return AVERROR(ENOMEM); - av_frame_unref(frame); + if (!ifilter_has_all_input_formats(fg)) { + AVFrame *tmp = av_frame_clone(frame); + if (!tmp) + return AVERROR(ENOMEM); + av_frame_unref(frame); - if (!av_fifo_space(ifilter->frame_queue)) { - ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); - if (ret < 0) { - av_frame_free(&tmp); - return ret; - } + if (!av_fifo_space(ifilter->frame_queue)) { + ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); + if (ret < 0) { + av_frame_free(&tmp); + return ret; } - av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); - return 0; } + av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); + return 0; + } ret = reap_filters(1); if (ret < 0 && ret != AVERROR_EOF) { From 99a49f91474b7c3836e007d366824bf3827e0009 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Wed, 13 Oct 2021 05:49:23 +0000 Subject: [PATCH 146/894] avutil/opt: fix mis-alignment of option and constant values for filter help Before: overlay AVOptions: x ..FV....... set the x expression (default "0") y ..FV....... set the y expression (default "0") eof_action ..FV....... Action to take when encountering EOF from secondary input (from 0 to 2) (default repeat) repeat 0 ..FV....... Repeat the previous frame. endall 1 ..FV....... End both streams. pass 2 ..FV....... Pass through the main input. eval ..FV....... specify when to evaluate expressions (from 0 to 1) (default frame) After: a overlay AVOptions: x ..FV....... set the x expression (default "0") y ..FV....... set the y expression (default "0") eof_action ..FV....... Action to take when encountering EOF from secondary input (from 0 to 2) (default repeat) repeat 0 ..FV....... Repeat the previous frame. endall 1 ..FV....... End both streams. pass 2 ..FV....... Pass through the main input. eval ..FV....... specify when to evaluate expressions (from 0 to 1) (default frame) Signed-off-by: softworkz Signed-off-by: Marton Balint --- libavutil/opt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index cfda31ea2f..d951edca9d 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -1173,7 +1173,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); else av_log(av_log_obj, AV_LOG_INFO, " %s%-17s ", - (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-", + (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? " " : "-", opt->name); switch (opt->type) { From ce47ce079ae0e1f60ccca3d614181a4ba05cc2e2 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Wed, 13 Oct 2021 08:34:10 +0000 Subject: [PATCH 147/894] fftools/ffmpeg: Output log message when interactive q command is received When viewing logs, it's sometimes useful to be able to see whether execution was ended via q command. Signed-off-by: softworkz Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 7545b7c68e..d141f34df9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3991,8 +3991,10 @@ static int check_keyboard_interaction(int64_t cur_time) last_time = cur_time; }else key = -1; - if (key == 'q') + if (key == 'q') { + av_log(NULL, AV_LOG_INFO, "\n\n[q] command received. Exiting.\n\n"); return AVERROR_EXIT; + } if (key == '+') av_log_set_level(av_log_get_level()+10); if (key == '-') av_log_set_level(av_log_get_level()-10); if (key == 's') qp_hist ^= 1; From f3b6e3e81aad9adb454cee2983d55455e2fc3ec2 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Wed, 13 Oct 2021 12:08:57 +0000 Subject: [PATCH 148/894] fftools/cmdutils: Print bit depths when executing 'ffmpeg -pix_fmts' New output looks like this: Pixel formats: I.... = Supported Input format for conversion .O... = Supported Output format for conversion ..H.. = Hardware accelerated format ...P. = Paletted format ....B = Bitstream format FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL BIT_DEPTHS ----- IO... yuv420p 3 12 8-8-8 IO... yuyv422 3 16 8-8-8 IO... rgb24 3 24 8-8-8 IO... bgr24 3 24 8-8-8 IO... yuv422p 3 16 8-8-8 IO... yuv444p 3 24 8-8-8 [..] Signed-off-by: softworkz Signed-off-by: Marton Balint --- fftools/cmdutils.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 2c8e98982f..426ba6c99f 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1754,7 +1754,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) "..H.. = Hardware accelerated format\n" "...P. = Paletted format\n" "....B = Bitstream format\n" - "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL\n" + "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL BIT_DEPTHS\n" "-----\n"); #if !CONFIG_SWSCALE @@ -1764,7 +1764,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc); - printf("%c%c%c%c%c %-16s %d %2d\n", + printf("%c%c%c%c%c %-16s %d %3d %d", sws_isSupportedInput (pix_fmt) ? 'I' : '.', sws_isSupportedOutput(pix_fmt) ? 'O' : '.', pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL ? 'H' : '.', @@ -1772,7 +1772,12 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.', pix_desc->name, pix_desc->nb_components, - av_get_bits_per_pixel(pix_desc)); + av_get_bits_per_pixel(pix_desc), + pix_desc->comp[0].depth); + + for (unsigned i = 1; i < pix_desc->nb_components; i++) + printf("-%d", pix_desc->comp[i].depth); + printf("\n"); } return 0; } From 58dce6f010dd1c083308a7f582990e90432e2967 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Sat, 16 Oct 2021 20:50:13 +0000 Subject: [PATCH 149/894] swscale/swscale: check SWS_PRINT_INFO flag for printing alignment warnings This makes output consistent with a similar warning just few lines above where this flag is checked in the same way. Signed-off-by: softworkz Signed-off-by: Marton Balint --- libswscale/swscale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 75cde31f4f..feef3482d2 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -329,7 +329,7 @@ static int swscale(SwsContext *c, const uint8_t *src[], ) { SwsContext *const ctx = c->parent ? c->parent : c; int cpu_flags = av_get_cpu_flags(); - if (HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) && + if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) && !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) { av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n"); } From c980dd7a976635426f129417836251740e19b54b Mon Sep 17 00:00:00 2001 From: Matthew White Date: Sun, 14 Nov 2021 00:42:27 +0000 Subject: [PATCH 150/894] doc/t2h.pm: fix missing CSS with texinfo 6.8 and above Since texinfo commit 6a5ceab6a48a4f052baad9f3474d741428409fd7, the formatting functions, in particular begin_file, program_string and end_file, are prefixed with format_, i.e. format_begin_file, etc. This patch fixes building the documentation when texinfo 6.8, or above, is used: Unknown formatting type begin_file at /usr/bin/makeinfo line 415. Unknown formatting type program_string at /usr/bin/makeinfo line 415. Unknown formatting type end_file at /usr/bin/makeinfo line 415. --- doc/t2h.pm | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/doc/t2h.pm b/doc/t2h.pm index e83d564a65..87412699aa 100644 --- a/doc/t2h.pm +++ b/doc/t2h.pm @@ -126,6 +126,10 @@ foreach my $command (keys(%Texinfo::Common::sectioning_commands), 'node') { texinfo_register_command_formatting($command, \&ffmpeg_heading_command); } +# determine if texinfo is at least version 6.8 +my $program_version_num = version->declare(get_conf('PACKAGE_VERSION'))->numify; +my $program_version_6_8 = $program_version_num >= 6.008000; + # print the TOC where @contents is used set_from_init_file('INLINE_CONTENTS', 1); @@ -184,7 +188,11 @@ EOT return $head1 . $head_title . $head2 . $head_title . $head3; } -texinfo_register_formatting_function('begin_file', \&ffmpeg_begin_file); +if ($program_version_6_8) { + texinfo_register_formatting_function('format_begin_file', \&ffmpeg_begin_file); +} else { + texinfo_register_formatting_function('begin_file', \&ffmpeg_begin_file); +} sub ffmpeg_program_string($) { @@ -201,7 +209,11 @@ sub ffmpeg_program_string($) $self->gdt('This document was generated automatically.')); } } -texinfo_register_formatting_function('program_string', \&ffmpeg_program_string); +if ($program_version_6_8) { + texinfo_register_formatting_function('format_program_string', \&ffmpeg_program_string); +} else { + texinfo_register_formatting_function('program_string', \&ffmpeg_program_string); +} # Customized file ending sub ffmpeg_end_file($) @@ -220,7 +232,11 @@ EOT EOT return $program_text . $footer; } -texinfo_register_formatting_function('end_file', \&ffmpeg_end_file); +if ($program_version_6_8) { + texinfo_register_formatting_function('format_end_file', \&ffmpeg_end_file); +} else { + texinfo_register_formatting_function('end_file', \&ffmpeg_end_file); +} # Dummy title command # Ignore title. Title is handled through ffmpeg_begin_file(). From bfbd5954e50e407693932b3900ca77c3daee26d7 Mon Sep 17 00:00:00 2001 From: Matthew White Date: Sun, 14 Nov 2021 01:10:58 +0000 Subject: [PATCH 151/894] doc/t2h.pm: fix missing TOC with texinfo 6.8 and above Since texinfo 6.8, there's no longer an INLINE_CONTENTS variable. makeinfo: warning: set_from_init_file: unknown variable INLINE_CONTENTS texinfo commit 62a6adfb33b006e187483779974bbd45f0f782b1 replaced INLINE_CONTENTS with OUTPUT_CONTENTS_LOCATION. texinfo commit 41f8ed4eb42bf6daa7df7007afd946875597452d replaced OUTPUT_CONTENTS_LOCATION with CONTENTS_OUTPUT_LOCATION. With texinfo 6.8 and above, the same as INLINE_CONTENTS=1 could be achieved by CONTENTS_OUTPUT_LOCATION=inline. https://www.gnu.org/software/texinfo/manual/texinfo/html_node/HTML-Customization-Variables.html --- doc/t2h.pm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/t2h.pm b/doc/t2h.pm index 87412699aa..d07d974286 100644 --- a/doc/t2h.pm +++ b/doc/t2h.pm @@ -131,7 +131,11 @@ my $program_version_num = version->declare(get_conf('PACKAGE_VERSION'))->numify; my $program_version_6_8 = $program_version_num >= 6.008000; # print the TOC where @contents is used -set_from_init_file('INLINE_CONTENTS', 1); +if ($program_version_6_8) { + set_from_init_file('CONTENTS_OUTPUT_LOCATION', 'inline'); +} else { + set_from_init_file('INLINE_CONTENTS', 1); +} # make chapters

set_from_init_file('CHAPTER_HEADER_LEVEL', 2); From fedf4ff85c325fa164a5646785104aaa292c877b Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 13 Nov 2021 18:59:07 +0100 Subject: [PATCH 152/894] avutil/vulkan: load win32 external memory functions --- libavutil/hwcontext_vulkan.h | 3 +++ libavutil/vulkan_functions.h | 12 ++++++++++++ libavutil/vulkan_loader.h | 9 ++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index c83fe3fb1d..fdf2a60156 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -19,6 +19,9 @@ #ifndef AVUTIL_HWCONTEXT_VULKAN_H #define AVUTIL_HWCONTEXT_VULKAN_H +#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR) +#define VK_USE_PLATFORM_WIN32_KHR +#endif #include #include "pixfmt.h" diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 913667befb..f6881d8959 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -27,6 +27,10 @@ typedef enum FFVulkanExtensions { FF_VK_EXT_EXTERNAL_FD_SEM = 1ULL << 3, /* VK_KHR_external_semaphore_fd */ FF_VK_EXT_EXTERNAL_HOST_MEMORY = 1ULL << 4, /* VK_EXT_external_memory_host */ FF_VK_EXT_DEBUG_UTILS = 1ULL << 5, /* VK_EXT_debug_utils */ +#ifdef _WIN32 + FF_VK_EXT_EXTERNAL_WIN32_MEMORY = 1ULL << 6, /* VK_KHR_external_memory_win32 */ + FF_VK_EXT_EXTERNAL_WIN32_SEM = 1ULL << 7, /* VK_KHR_external_semaphore_win32 */ +#endif FF_VK_EXT_NO_FLAG = 1ULL << 63, } FFVulkanExtensions; @@ -151,6 +155,11 @@ typedef enum FFVulkanExtensions { MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateShaderModule) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyShaderModule) +/* Macro containing every win32 specific function that we utilize in our codebase */ +#define FN_LIST_WIN32(MACRO) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_SEM, GetSemaphoreWin32HandleKHR) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_MEMORY, GetMemoryWin32HandleKHR) + /* Macro to turn a function name into a definition */ #define PFN_DEF(req_inst, req_dev, ext_flag, name) \ PFN_vk##name name; @@ -158,6 +167,9 @@ typedef enum FFVulkanExtensions { /* Structure with the definition of all listed functions */ typedef struct FFVulkanFunctions { FN_LIST(PFN_DEF) +#ifdef _WIN32 + FN_LIST_WIN32(PFN_DEF) +#endif } FFVulkanFunctions; #endif /* AVUTIL_VULKAN_FUNCTIONS_H */ diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index 838d26d271..d4e05e62d7 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -43,7 +43,11 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, - { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS } + { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS }, +#ifdef _WIN32 + { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, +#endif }; FFVulkanExtensions mask = 0x0; @@ -88,6 +92,9 @@ static inline int ff_vk_load_functions(AVHWDeviceContext *ctx, const char *names[3]; } vk_load_info[] = { FN_LIST(PFN_LOAD_INFO) +#ifdef _WIN32 + FN_LIST_WIN32(PFN_LOAD_INFO) +#endif }; for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) { From 2ece70090d61ccc1aea8000ba57d2fd759f204f7 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 13 Nov 2021 20:00:50 +0100 Subject: [PATCH 153/894] avutil/hwcontext_vulkan: add support for exporting memory via Win32 Handles --- libavutil/hwcontext_vulkan.c | 102 ++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index d40b1e5de0..b218b6c411 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -21,6 +21,7 @@ #ifdef _WIN32 #include /* Included to prevent conflicts with CreateSemaphore */ +#include #include "compat/w32dlfcn.h" #else #include @@ -123,6 +124,10 @@ typedef struct AVVkFrameInternal { CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS]; CUarray cu_array[AV_NUM_DATA_POINTERS]; CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS]; +#ifdef _WIN32 + HANDLE ext_mem_handle[AV_NUM_DATA_POINTERS]; + HANDLE ext_sem_handle[AV_NUM_DATA_POINTERS]; +#endif #endif } AVVkFrameInternal; @@ -309,6 +314,10 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS }, { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, +#ifdef _WIN32 + { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, +#endif /* Video encoding/decoding */ { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, @@ -1575,6 +1584,12 @@ static void vulkan_free_internal(AVVkFrame *f) CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i])); if (internal->ext_mem[i]) CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i])); +#ifdef _WIN32 + if (internal->ext_sem_handle[i]) + CloseHandle(internal->ext_sem_handle[i]); + if (internal->ext_mem_handle[i]) + CloseHandle(internal->ext_mem_handle[i]); +#endif } av_buffer_unref(&internal->cuda_fc_ref); @@ -1811,12 +1826,22 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkExportSemaphoreCreateInfo ext_sem_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, +#ifdef _WIN32 + .handleTypes = IsWindows8OrGreater() + ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, +#else .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, +#endif }; VkSemaphoreTypeCreateInfo sem_type_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, +#ifdef _WIN32 + .pNext = p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM ? &ext_sem_info : NULL, +#else .pNext = p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, +#endif .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, .initialValue = 0, }; @@ -1947,6 +1972,12 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) .pNext = hwctx->create_pnext, }; +#ifdef _WIN32 + if (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) + try_export_flags(hwfc, &eiinfo.handleTypes, &e, IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); +#else if (p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); @@ -1954,6 +1985,7 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); +#endif for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) { eminfo[i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; @@ -2651,6 +2683,43 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, }, .numLevels = 1, }; + int p_w, p_h; + +#ifdef _WIN32 + CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = { + .type = IsWindows8OrGreater() + ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32 + : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT, + .size = dst_f->size[i], + }; + VkMemoryGetWin32HandleInfoKHR export_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, + .memory = dst_f->mem[i], + .handleType = IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + }; + VkSemaphoreGetWin32HandleInfoKHR sem_export = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR, + .semaphore = dst_f->sem[i], + .handleType = IsWindows8OrGreater() + ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + }; + CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = { + .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */, + }; + + ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info, + &ext_desc.handle.win32.handle); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + dst_int->ext_mem_handle[i] = ext_desc.handle.win32.handle; +#else CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = { .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD, .size = dst_f->size[i], @@ -2669,12 +2738,6 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */, }; - int p_w, p_h; - get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i); - - tex_desc.arrayDesc.Width = p_w; - tex_desc.arrayDesc.Height = p_h; - ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info, &ext_desc.handle.fd); if (ret != VK_SUCCESS) { @@ -2683,14 +2746,21 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, err = AVERROR_EXTERNAL; goto fail; } +#endif ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[i], &ext_desc)); if (ret < 0) { +#ifndef _WIN32 close(ext_desc.handle.fd); +#endif err = AVERROR_EXTERNAL; goto fail; } + get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i); + tex_desc.arrayDesc.Width = p_w; + tex_desc.arrayDesc.Height = p_h; + ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i], dst_int->ext_mem[i], &tex_desc)); @@ -2706,19 +2776,29 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, goto fail; } +#ifdef _WIN32 + ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export, + &ext_sem_desc.handle.win32.handle); +#else ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export, &ext_sem_desc.handle.fd); +#endif if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n", vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } +#ifdef _WIN32 + dst_int->ext_sem_handle[i] = ext_sem_desc.handle.win32.handle; +#endif ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[i], &ext_sem_desc)); if (ret < 0) { +#ifndef _WIN32 close(ext_sem_desc.handle.fd); +#endif err = AVERROR_EXTERNAL; goto fail; } @@ -3544,8 +3624,13 @@ static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, switch (src->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: +#ifdef _WIN32 + if ((p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM)) +#else if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) +#endif return vulkan_transfer_data_from_cuda(hwfc, dst, src); #endif default: @@ -3657,8 +3742,13 @@ static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: +#ifdef _WIN32 + if ((p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM)) +#else if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) +#endif return vulkan_transfer_data_to_cuda(hwfc, dst, src); #endif default: From 74e49cc583fbc6a0dd06f8f6eb1ba2f5f340d547 Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Sat, 13 Nov 2021 18:56:52 -0800 Subject: [PATCH 154/894] swscale/input: unify grayf32 funcs with rgbf32 funcs This is ment to be a cosmetic change old timings: 42780 UNITS in grayf32le, 1 runs, 0 skips 56720 UNITS in grayf32le, 2 runs, 0 skips 67265 UNITS in grayf32le, 4 runs, 0 skips 58082 UNITS in grayf32le, 8 runs, 0 skips 63512 UNITS in grayf32le, 16 runs, 0 skips 52720 UNITS in grayf32le, 32 runs, 0 skips 46491 UNITS in grayf32le, 64 runs, 0 skips 68500 UNITS in grayf32be, 1 runs, 0 skips 66930 UNITS in grayf32be, 2 runs, 0 skips 62305 UNITS in grayf32be, 4 runs, 0 skips 55510 UNITS in grayf32be, 8 runs, 0 skips 50216 UNITS in grayf32be, 16 runs, 0 skips 44480 UNITS in grayf32be, 32 runs, 0 skips 42394 UNITS in grayf32be, 64 runs, 0 skips new timings: 46660 UNITS in grayf32le, 1 runs, 0 skips 51830 UNITS in grayf32le, 2 runs, 0 skips 53390 UNITS in grayf32le, 4 runs, 0 skips 50910 UNITS in grayf32le, 8 runs, 0 skips 44968 UNITS in grayf32le, 16 runs, 0 skips 40349 UNITS in grayf32le, 32 runs, 0 skips 38330 UNITS in grayf32le, 64 runs, 0 skips 39980 UNITS in grayf32be, 1 runs, 0 skips 49630 UNITS in grayf32be, 2 runs, 0 skips 53540 UNITS in grayf32be, 4 runs, 0 skips 59767 UNITS in grayf32be, 8 runs, 0 skips 51206 UNITS in grayf32be, 16 runs, 0 skips 44743 UNITS in grayf32be, 32 runs, 0 skips 41468 UNITS in grayf32be, 64 runs, 0 skips Signed-off-by: Michael Niedermayer --- libswscale/input.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/libswscale/input.c b/libswscale/input.c index 336f957c8c..90efdd2ffc 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -1013,31 +1013,19 @@ static av_always_inline void planar_rgbf32_to_y(uint8_t *_dst, const uint8_t *_s } } -#undef rdpx - static av_always_inline void grayf32ToY16_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, - const uint8_t *unused2, int width, uint32_t *unused) + const uint8_t *unused2, int width, int is_be, uint32_t *unused) { int i; const float *src = (const float *)_src; uint16_t *dst = (uint16_t *)_dst; for (i = 0; i < width; ++i){ - dst[i] = av_clip_uint16(lrintf(65535.0f * src[i])); + dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src + i))); } } -static av_always_inline void grayf32ToY16_bswap_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, - const uint8_t *unused2, int width, uint32_t *unused) -{ - int i; - const uint32_t *src = (const uint32_t *)_src; - uint16_t *dst = (uint16_t *)_dst; - - for (i = 0; i < width; ++i){ - dst[i] = av_clip_uint16(lrintf(65535.0f * av_int2float(av_bswap32(src[i])))); - } -} +#undef rdpx #define rgb9plus_planar_funcs_endian(nbits, endian_name, endian) \ static void planar_rgb##nbits##endian_name##_to_y(uint8_t *dst, const uint8_t *src[4], \ @@ -1092,6 +1080,12 @@ static void planar_rgbf32##endian_name##_to_a(uint8_t *dst, const uint8_t *src[4 int w, int32_t *rgb2yuv) \ { \ planar_rgbf32_to_a(dst, src, w, endian, rgb2yuv); \ +} \ +static void grayf32##endian_name##ToY16_c(uint8_t *dst, const uint8_t *src, \ + const uint8_t *unused1, const uint8_t *unused2, \ + int width, uint32_t *unused) \ +{ \ + grayf32ToY16_c(dst, src, unused1, unused2, width, endian, unused); \ } rgbf32_planar_funcs_endian(le, 0) @@ -1699,18 +1693,10 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->lumToYV12 = p010BEToY_c; break; case AV_PIX_FMT_GRAYF32LE: -#if HAVE_BIGENDIAN - c->lumToYV12 = grayf32ToY16_bswap_c; -#else - c->lumToYV12 = grayf32ToY16_c; -#endif + c->lumToYV12 = grayf32leToY16_c; break; case AV_PIX_FMT_GRAYF32BE: -#if HAVE_BIGENDIAN - c->lumToYV12 = grayf32ToY16_c; -#else - c->lumToYV12 = grayf32ToY16_bswap_c; -#endif + c->lumToYV12 = grayf32beToY16_c; break; case AV_PIX_FMT_Y210LE: c->lumToYV12 = y210le_Y_c; From 866ad2e95262606b194cb2e79ce8a7e63c32ce06 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 15 Oct 2021 00:01:06 +0200 Subject: [PATCH 155/894] avcodec/speexdec: Check frames_per_packet more completely Fixes: signed integer overflow: 2105344 * 539033345 cannot be represented in type 'int' Fixes: out of array write Fixes: 39956/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SPEEX_fuzzer-4766419250708480 Fixes: 40293/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SPEEX_fuzzer-5219910217760768 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/speexdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c index 90e95f0785..e263d4c48c 100644 --- a/libavcodec/speexdec.c +++ b/libavcodec/speexdec.c @@ -1423,7 +1423,9 @@ static int parse_speex_extradata(AVCodecContext *avctx, return AVERROR_INVALIDDATA; s->vbr = bytestream_get_le32(&buf); s->frames_per_packet = bytestream_get_le32(&buf); - if (s->frames_per_packet <= 0) + if (s->frames_per_packet <= 0 || + s->frames_per_packet > 64 || + s->frames_per_packet >= INT32_MAX / s->nb_channels / s->frame_size) return AVERROR_INVALIDDATA; s->extra_headers = bytestream_get_le32(&buf); From 97c3053d59f30f84b30efcc73ccf1b2e84b89006 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 17 Oct 2021 15:15:08 +0200 Subject: [PATCH 156/894] avformat/dhav: Limit get_duration() iterations Fixes: Timeout Fixes: 39971/clusterfuzz-testcase-minimized-ffmpeg_IO_DEMUXER_fuzzer-5756969890217984 Fixes: 39977/clusterfuzz-testcase-minimized-ffmpeg_dem_DHAV_fuzzer-5327123053674496 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/dhav.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/dhav.c b/libavformat/dhav.c index b6bb25204c..6c1cdde32c 100644 --- a/libavformat/dhav.c +++ b/libavformat/dhav.c @@ -234,12 +234,13 @@ static int64_t get_duration(AVFormatContext *s) int64_t start_pos = avio_tell(s->pb); int64_t start = 0, end = 0; struct tm timeinfo; + int max_interations = 100000; if (!s->pb->seekable) return 0; avio_seek(s->pb, avio_size(s->pb) - 8, SEEK_SET); - while (avio_tell(s->pb) > 12) { + while (avio_tell(s->pb) > 12 && max_interations--) { if (avio_rl32(s->pb) == MKTAG('d','h','a','v')) { int seek_back = avio_rl32(s->pb); From 0a9edac48eacc0f914f489dc7953a51bf24bb99c Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 28 Jul 2021 23:53:42 +0200 Subject: [PATCH 157/894] avfilter/af_apad: do not add infinite silence for zero pad_dur or whole_dur Unfortunately pad_len and pad_dur behaviour was different if 0 was specified, pad_dur handled 0 duration as infinity, for pad_len, infinity was -1. Let's make the behaviour consistent by handling 0 duration for pad_dur and whole_dur as indeed 0 duration. This somewhat changes the behaviour of the filter if 0 was explicitly specified, but deprecating the old option and adding a new for the corrected behaviour seemed a bit overkill. So let's document the change instead. Signed-off-by: Marton Balint --- doc/filters.texi | 7 +++++-- libavfilter/af_apad.c | 8 ++++---- libavfilter/version.h | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6ab41706e5..1fced203b6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2291,12 +2291,12 @@ with @option{pad_len}. @item pad_dur Specify the duration of samples of silence to add. See @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} -for the accepted syntax. Used only if set to non-zero value. +for the accepted syntax. Used only if set to non-negative value. @item whole_dur Specify the minimum total duration in the output audio stream. See @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} -for the accepted syntax. Used only if set to non-zero value. If the value is longer than +for the accepted syntax. Used only if set to non-negative value. If the value is longer than the input audio length, silence is added to the end, until the value is reached. This option is mutually exclusive with @option{pad_dur} @end table @@ -2305,6 +2305,9 @@ If neither the @option{pad_len} nor the @option{whole_len} nor @option{pad_dur} nor @option{whole_dur} option is set, the filter will add silence to the end of the input stream indefinitely. +Note that for ffmpeg 4.4 and earlier a zero @option{pad_dur} or +@option{whole_dur} also caused the filter to add silence indefinitely. + @subsection Examples @itemize diff --git a/libavfilter/af_apad.c b/libavfilter/af_apad.c index 27259a87a3..ae73f0b6b1 100644 --- a/libavfilter/af_apad.c +++ b/libavfilter/af_apad.c @@ -52,8 +52,8 @@ static const AVOption apad_options[] = { { "packet_size", "set silence packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 0, INT_MAX, A }, { "pad_len", "set number of samples of silence to add", OFFSET(pad_len), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, A }, { "whole_len", "set minimum target number of samples in the audio stream", OFFSET(whole_len), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, A }, - { "pad_dur", "set duration of silence to add", OFFSET(pad_dur), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, A }, - { "whole_dur", "set minimum target duration in the audio stream", OFFSET(whole_dur), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, A }, + { "pad_dur", "set duration of silence to add", OFFSET(pad_dur), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, A }, + { "whole_dur", "set minimum target duration in the audio stream", OFFSET(whole_dur), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, A }, { NULL } }; @@ -138,9 +138,9 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; APadContext *s = ctx->priv; - if (s->pad_dur) + if (s->pad_dur >= 0) s->pad_len = av_rescale(s->pad_dur, outlink->sample_rate, AV_TIME_BASE); - if (s->whole_dur) + if (s->whole_dur >= 0) s->whole_len = av_rescale(s->whole_dur, outlink->sample_rate, AV_TIME_BASE); s->pad_len_left = s->pad_len; diff --git a/libavfilter/version.h b/libavfilter/version.h index 3bd3816698..1a4d0a75cd 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 8 #define LIBAVFILTER_VERSION_MINOR 16 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 406ffd9b9b99fa096bcfe31b467453824d1542e7 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 7 Nov 2021 18:21:17 +0100 Subject: [PATCH 158/894] avformat/demux: allow total size of packets in raw_packet_buffer to reach probesize Previously this was hardcoded to 2500000 bytes, so probing of the stream codecs was always limited by this, and not probesize. Also keep track of the actual size of packets in raw_packet_buffer and not the remaining size for simplicity. Fixes ticket #5860. Signed-off-by: Marton Balint --- libavformat/demux.c | 10 +++++----- libavformat/internal.h | 5 ++--- libavformat/options.c | 1 - libavformat/utils.c | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libavformat/demux.c b/libavformat/demux.c index 71a1a9bf03..745dc8687c 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -328,7 +328,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, if (s->pb && !si->data_offset) si->data_offset = avio_tell(s->pb); - si->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; + si->raw_packet_buffer_size = 0; update_stream_avctx(s); @@ -432,7 +432,7 @@ no_packet: } } - end = si->raw_packet_buffer_remaining_size <= 0 + end = si->raw_packet_buffer_size >= s->probesize || sti->probe_packets <= 0; if (end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) { @@ -544,13 +544,13 @@ FF_ENABLE_DEPRECATION_WARNINGS if (pktl) { AVStream *const st = s->streams[pktl->pkt.stream_index]; - if (si->raw_packet_buffer_remaining_size <= 0) + if (si->raw_packet_buffer_size >= s->probesize) if ((err = probe_codec(s, st, NULL)) < 0) return err; if (ffstream(st)->request_probe <= 0) { avpriv_packet_list_get(&si->raw_packet_buffer, &si->raw_packet_buffer_end, pkt); - si->raw_packet_buffer_remaining_size += pkt->size; + si->raw_packet_buffer_size -= pkt->size; return 0; } } @@ -631,7 +631,7 @@ FF_ENABLE_DEPRECATION_WARNINGS return err; } pkt1 = &si->raw_packet_buffer_end->pkt; - si->raw_packet_buffer_remaining_size -= pkt1->size; + si->raw_packet_buffer_size += pkt1->size; if ((err = probe_codec(s, st, pkt1)) < 0) return err; diff --git a/libavformat/internal.h b/libavformat/internal.h index f1ae7db365..1f301dd17a 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -127,10 +127,9 @@ typedef struct FFFormatContext { */ AVPacket *pkt; /** - * Remaining size available for raw_packet_buffer, in bytes. + * Sum of the size of packets in raw_packet_buffer, in bytes. */ -#define RAW_PACKET_BUFFER_SIZE 2500000 - int raw_packet_buffer_remaining_size; + int raw_packet_buffer_size; /** * Offset to remap timestamps to be non-negative. diff --git a/libavformat/options.c b/libavformat/options.c index 753aa9b8dc..72c9bdcefe 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -174,7 +174,6 @@ AVFormatContext *avformat_alloc_context(void) } si->offset = AV_NOPTS_VALUE; - si->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; si->shortest_end = AV_NOPTS_VALUE; return s; diff --git a/libavformat/utils.c b/libavformat/utils.c index 509c0ecdce..bbc61dccbb 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -303,7 +303,7 @@ void ff_flush_packet_queue(AVFormatContext *s) avpriv_packet_list_free(&si->packet_buffer, &si->packet_buffer_end); avpriv_packet_list_free(&si->raw_packet_buffer, &si->raw_packet_buffer_end); - si->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; + si->raw_packet_buffer_size = 0; } int av_find_default_stream_index(AVFormatContext *s) From 23a1f11d02a29b788d441e1b0846a28c0f479df9 Mon Sep 17 00:00:00 2001 From: Googleplex Date: Fri, 12 Nov 2021 14:29:11 +0800 Subject: [PATCH 159/894] avformat/concatdec: fix NEEDS_UNSAFE flag value NEEDS_UNSAFE has the same value as NEEDS_FILE, causing "duration not allowed if safe" error while duration directive doesn't require unsafe mode. Signed-off-by: Googleplex --- libavformat/concatdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 2557f38b26..8d80e536d1 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -409,7 +409,7 @@ static int concat_read_close(AVFormatContext *avf) } #define MAX_ARGS 3 -#define NEEDS_UNSAFE (1 << 1) +#define NEEDS_UNSAFE (1 << 0) #define NEEDS_FILE (1 << 1) #define NEEDS_STREAM (1 << 2) From 9e8cdb24cd2001959b37b08254d4c0cbc5668717 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 15 Nov 2021 17:16:56 +0530 Subject: [PATCH 160/894] doc/filters: add details and ranges for colorkey --- doc/filters.texi | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 1fced203b6..3aa54e6c69 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8496,25 +8496,31 @@ This filter supports the all above options as @ref{commands}. @section colorkey RGB colorspace color keying. +This filter operates on 8-bit RGB format frames by setting the alpha component of each pixel +which falls within the similarity radius of the key color to 0. The alpha value for pixels outside +the similarity radius depends on the value of the blend option. The filter accepts the following options: @table @option @item color -The color which will be replaced with transparency. +Set the color for which alpha will be set to 0 (full transparency). +See @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. +Default is @code{black}. @item similarity -Similarity percentage with the key color. - -0.01 matches only the exact key color, while 1.0 matches everything. +Set the radius from the key color within which other colors also have full transparency. +The computed distance is related to the unit fractional distance in 3D space between the RGB values +of the key color and the pixel's color. Range is 0.01 to 1.0. 0.01 matches within a very small radius +around the exact key color, while 1.0 matches everything. +Default is @code{0.01}. @item blend -Blend percentage. - -0.0 makes pixels either fully transparent, or not transparent at all. - -Higher values result in semi-transparent pixels, with a higher transparency -the more similar the pixels color is to the key color. +Set how the alpha value for pixels that fall outside the similarity radius is computed. +0.0 makes pixels either fully transparent or fully opaque. +Higher values result in semi-transparent pixels, with greater transparency +the more similar the pixel color is to the key color. +Range is 0.0 to 1.0. Default is @code{0.0}. @end table @subsection Examples From db932241ee16868475fe9ab4c958fcffd1829ecf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 14:26:23 +0100 Subject: [PATCH 161/894] */version.h: define FF_API macros unconditionally There is no reason to wrap them in #ifndef guards, they should only be defined here and nowhere else. The define guards just add the possibility to accidentally use the same FF_API name in different libraries. --- libavcodec/version.h | 24 ------------------------ libavdevice/version.h | 2 -- libavfilter/version.h | 6 ------ libavformat/version.h | 8 -------- libavutil/version.h | 8 -------- 5 files changed, 48 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 74b8baa5f3..7d4cfa3f11 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -51,41 +51,17 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#ifndef FF_API_OPENH264_SLICE_MODE #define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_OPENH264_CABAC #define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_UNUSED_CODEC_CAPS #define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_THREAD_SAFE_CALLBACKS #define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_DEBUG_MV #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_GET_FRAME_CLASS #define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_AUTO_THREADS #define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_INIT_PACKET #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_MPEGVIDEO_OPTS #define FF_API_MPEGVIDEO_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_FLAG_TRUNCATED #define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_SUB_TEXT_FORMAT #define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) -#endif #endif /* AVCODEC_VERSION_H */ diff --git a/libavdevice/version.h b/libavdevice/version.h index 8daeb0059a..914e156ec7 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -46,8 +46,6 @@ * dropped at a future version bump. The defines themselves are not part of * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_DEVICE_CAPABILITIES #define FF_API_DEVICE_CAPABILITIES (LIBAVDEVICE_VERSION_MAJOR < 60) -#endif #endif /* AVDEVICE_VERSION_H */ diff --git a/libavfilter/version.h b/libavfilter/version.h index 1a4d0a75cd..0912af7afe 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -50,14 +50,8 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_SWS_PARAM_OPTION #define FF_API_SWS_PARAM_OPTION (LIBAVFILTER_VERSION_MAJOR < 9) -#endif -#ifndef FF_API_BUFFERSINK_ALLOC #define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) -#endif -#ifndef FF_API_PAD_COUNT #define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) -#endif #endif /* AVFILTER_VERSION_H */ diff --git a/libavformat/version.h b/libavformat/version.h index 81ed517609..2e860b8d76 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -55,18 +55,10 @@ * at once through the bump. This improves the git bisect-ability of the change. * */ -#ifndef FF_API_LAVF_PRIV_OPT #define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_COMPUTE_PKT_FIELDS2 #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_AVIOCONTEXT_WRITTEN #define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_R_FRAME_RATE #define FF_API_R_FRAME_RATE 1 -#endif #endif /* AVFORMAT_VERSION_H */ diff --git a/libavutil/version.h b/libavutil/version.h index eeb33b388c..5ebef06829 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -105,18 +105,10 @@ * @{ */ -#ifndef FF_API_D2STR #define FF_API_D2STR (LIBAVUTIL_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_DECLARE_ALIGNED #define FF_API_DECLARE_ALIGNED (LIBAVUTIL_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_COLORSPACE_NAME #define FF_API_COLORSPACE_NAME (LIBAVUTIL_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_AV_MALLOCZ_ARRAY #define FF_API_AV_MALLOCZ_ARRAY (LIBAVUTIL_VERSION_MAJOR < 58) -#endif /** * @} From a7dfa6b446e8ced9f25efd0597e6073e6b22a94b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 15 Nov 2021 11:22:53 +0100 Subject: [PATCH 162/894] avfilter/v360: add support for off-axis projection output --- doc/filters.texi | 5 ++++ libavfilter/v360.h | 1 + libavfilter/vf_v360.c | 56 ++++++++++++++----------------------------- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 3aa54e6c69..b4f888c14d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -21814,6 +21814,11 @@ Set if input video is transposed. Boolean value, by default disabled. @item out_trans Set if output video needs to be transposed. Boolean value, by default disabled. +@item h_offset +@item v_offset +Set output horizontal/vertical off-axis offset. Default is set to 0. +Allowed range is from -1 to 1. + @item alpha_mask Build mask in alpha plane for all unmapped pixels by marking them fully transparent. Boolean value, by default disabled. diff --git a/libavfilter/v360.h b/libavfilter/v360.h index 05e3435b44..5d797ab828 100644 --- a/libavfilter/v360.h +++ b/libavfilter/v360.h @@ -142,6 +142,7 @@ typedef struct V360Context { int fin_pad, fout_pad; float yaw, pitch, roll; + float h_offset, v_offset; int ih_flip, iv_flip; int h_flip, v_flip, d_flip; diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index 5df273d375..9e590a228c 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -163,6 +163,8 @@ static const AVOption v360_options[] = { { "ih_fov", "input horizontal field of view",OFFSET(ih_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "ih_fov"}, { "iv_fov", "input vertical field of view", OFFSET(iv_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "iv_fov"}, { "id_fov", "input diagonal field of view", OFFSET(id_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "id_fov"}, + { "h_offset", "output horizontal off-axis offset",OFFSET(h_offset), AV_OPT_TYPE_FLOAT,{.dbl=0.f}, -1.f, 1.f,TFLAGS, "h_offset"}, + { "v_offset", "output vertical off-axis offset", OFFSET(v_offset), AV_OPT_TYPE_FLOAT,{.dbl=0.f}, -1.f, 1.f,TFLAGS, "v_offset"}, {"alpha_mask", "build mask in alpha plane", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "alpha"}, { "reset_rot", "reset rotation", OFFSET(reset_rot), AV_OPT_TYPE_BOOL, {.i64=0}, -1, 1,TFLAGS, "reset_rot"}, { NULL } @@ -1027,6 +1029,17 @@ static inline void rotate_cube_face_inverse(float *uf, float *vf, int rotation) } } +/** + * Offset vector. + * + * @param vec vector + */ +static void offset_vector(float *vec, float h_offset, float v_offset) +{ + vec[0] += h_offset; + vec[1] += v_offset; +} + /** * Normalize vector. * @@ -1103,8 +1116,6 @@ static void cube_to_xyz(const V360Context *s, vec[0] = l_x; vec[1] = l_y; vec[2] = l_z; - - normalize_vector(vec); } /** @@ -1854,8 +1865,6 @@ static int stereographic_to_xyz(const V360Context *s, vec[1] = y / r * sin_theta; vec[2] = cosf(theta); - normalize_vector(vec); - return 1; } @@ -1960,8 +1969,6 @@ static int equisolid_to_xyz(const V360Context *s, vec[1] = y / r * sin_theta; vec[2] = cosf(theta); - normalize_vector(vec); - return 1; } @@ -2066,12 +2073,11 @@ static int orthographic_to_xyz(const V360Context *s, vec[0] = x; vec[1] = y; - normalize_vector(vec); return 1; } else { - vec[0] = 0; - vec[1] = 0; - vec[2] = 1; + vec[0] = 0.f; + vec[1] = 0.f; + vec[2] = 1.f; return 0; } @@ -2474,8 +2480,6 @@ static int hammer_to_xyz(const V360Context *s, vec[1] = M_SQRT2 * y * z; vec[2] = w * (bb - aa) / (aa + bb); - normalize_vector(vec); - return 1; } @@ -2546,8 +2550,6 @@ static int sinusoidal_to_xyz(const V360Context *s, vec[1] = sin_theta; vec[2] = cos_theta * cos_phi; - normalize_vector(vec); - return 1; } @@ -2743,8 +2745,6 @@ static int eac_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = l_z; - normalize_vector(vec); - return 1; } @@ -2846,8 +2846,6 @@ static int flat_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = 1.f; - normalize_vector(vec); - return 1; } @@ -2897,8 +2895,6 @@ static int fisheye_to_xyz(const V360Context *s, vec[1] = cos_theta * sin_phi; vec[2] = sin_theta; - normalize_vector(vec); - return 1; } @@ -2993,8 +2989,6 @@ static int pannini_to_xyz(const V360Context *s, vec[1] = sinf(lat); vec[2] = cosf(lon) * cosf(lat); - normalize_vector(vec); - return 1; } @@ -3090,8 +3084,6 @@ static int cylindrical_to_xyz(const V360Context *s, vec[1] = sin_theta; vec[2] = cos_theta * cos_phi; - normalize_vector(vec); - return 1; } @@ -3217,8 +3209,6 @@ static int cylindricalea_to_xyz(const V360Context *s, vec[1] = sin_theta; vec[2] = cos_theta * cos_phi; - normalize_vector(vec); - return 1; } @@ -3331,8 +3321,6 @@ static int tetrahedron_to_xyz(const V360Context *s, vec[1] = 1.f - vf * 2.f; vec[2] = 2.f * fabsf(1.f - fabsf(1.f - uf * 2.f + vf)) - 1.f; - normalize_vector(vec); - return 1; } @@ -3444,8 +3432,6 @@ static int dfisheye_to_xyz(const V360Context *s, vec[1] = cos_theta * vf / lh; vec[2] = sin_theta; - normalize_vector(vec); - return 1; } @@ -3568,8 +3554,6 @@ static int barrel_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = l_z; - normalize_vector(vec); - return 1; } @@ -3826,8 +3810,6 @@ static int barrelsplit_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = l_z; - normalize_vector(vec); - return 1; } @@ -3884,8 +3866,6 @@ static int tspyramid_to_xyz(const V360Context *s, vec[2] = -2.f * (1.f - y) / 0.375f + 1.f; } - normalize_vector(vec); - return 1; } @@ -3987,8 +3967,6 @@ static int octahedron_to_xyz(const V360Context *s, vec[1] = y; } - normalize_vector(vec); - return 1; } @@ -4293,6 +4271,8 @@ static av_always_inline int v360_slice(AVFilterContext *ctx, void *arg, int jobn out_mask = s->out_transform(s, j, i, height, width, vec); else out_mask = s->out_transform(s, i, j, width, height, vec); + offset_vector(vec, s->h_offset, s->v_offset); + normalize_vector(vec); av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2])); rotate(s->rot_quaternion, vec); av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2])); From c3502f4f75583a530bc54e2cb6754236d72f204b Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Sun, 14 Nov 2021 22:22:20 -0800 Subject: [PATCH 163/894] libavutil/common: clip nan value to amin Changes av_clipf to return amin if a is nan. Before if a is nan av_clipf_c returned nan and av_clipf_sse would return amax. Now the both should behave the same. This works because nan > amin is false. The max(nan, amin) will be amin. Signed-off-by: James Almer --- libavutil/common.h | 12 ++++++------ libavutil/x86/intmath.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libavutil/common.h b/libavutil/common.h index 3cc1f07566..3eb9bc5f74 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -379,6 +379,8 @@ static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { /** * Clip a float value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. * @param a value to clip * @param amin minimum value of the clip range * @param amax maximum value of the clip range @@ -389,13 +391,13 @@ static av_always_inline av_const float av_clipf_c(float a, float amin, float ama #if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - if (a < amin) return amin; - else if (a > amax) return amax; - else return a; + return FFMIN(FFMAX(a, amin), amax); } /** * Clip a double value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. * @param a value to clip * @param amin minimum value of the clip range * @param amax maximum value of the clip range @@ -406,9 +408,7 @@ static av_always_inline av_const double av_clipd_c(double a, double amin, double #if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - if (a < amin) return amin; - else if (a > amax) return amax; - else return a; + return FFMIN(FFMAX(a, amin), amax); } /** Compute ceil(log2(x)). diff --git a/libavutil/x86/intmath.h b/libavutil/x86/intmath.h index 40743fd13e..1520c25ec9 100644 --- a/libavutil/x86/intmath.h +++ b/libavutil/x86/intmath.h @@ -110,8 +110,8 @@ static av_always_inline av_const double av_clipd_sse2(double a, double amin, dou #if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - __asm__ ("minsd %2, %0 \n\t" - "maxsd %1, %0 \n\t" + __asm__ ("maxsd %1, %0 \n\t" + "minsd %2, %0 \n\t" : "+&x"(a) : "xm"(amin), "xm"(amax)); return a; } @@ -126,8 +126,8 @@ static av_always_inline av_const float av_clipf_sse(float a, float amin, float a #if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - __asm__ ("minss %2, %0 \n\t" - "maxss %1, %0 \n\t" + __asm__ ("maxss %1, %0 \n\t" + "minss %2, %0 \n\t" : "+&x"(a) : "xm"(amin), "xm"(amax)); return a; } From 3f4ce004b8afa915499c367e78ae080bc457624c Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Sun, 14 Nov 2021 22:22:21 -0800 Subject: [PATCH 164/894] swscale/input: clip rgbf32 values before lrintf if the float pixel * 65535.0f > 2147483647.0f lrintf may overfow and return negative values, depending on implementation. nan and +/-inf values may also be implementation defined clip the value first so lrintf always works. values < 0.0f, -inf, nan = 0.0f values > 65535.0f, +inf = 65535.0f old timings 195960 decicycles in planar_rgbf32le_to_uv, 1 runs, 0 skips 186120 decicycles in planar_rgbf32le_to_uv, 2 runs, 0 skips 188645 decicycles in planar_rgbf32le_to_uv, 4 runs, 0 skips 183625 decicycles in planar_rgbf32le_to_uv, 8 runs, 0 skips 181157 decicycles in planar_rgbf32le_to_uv, 16 runs, 0 skips 177533 decicycles in planar_rgbf32le_to_uv, 32 runs, 0 skips 175689 decicycles in planar_rgbf32le_to_uv, 64 runs, 0 skips 232960 decicycles in planar_rgbf32be_to_uv, 1 runs, 0 skips 221380 decicycles in planar_rgbf32be_to_uv, 2 runs, 0 skips 216640 decicycles in planar_rgbf32be_to_uv, 4 runs, 0 skips 213505 decicycles in planar_rgbf32be_to_uv, 8 runs, 0 skips 211558 decicycles in planar_rgbf32be_to_uv, 16 runs, 0 skips 210596 decicycles in planar_rgbf32be_to_uv, 32 runs, 0 skips 210202 decicycles in planar_rgbf32be_to_uv, 64 runs, 0 skips 161680 decicycles in planar_rgbf32le_to_y, 1 runs, 0 skips 153540 decicycles in planar_rgbf32le_to_y, 2 runs, 0 skips 148255 decicycles in planar_rgbf32le_to_y, 4 runs, 0 skips 140600 decicycles in planar_rgbf32le_to_y, 8 runs, 0 skips 132935 decicycles in planar_rgbf32le_to_y, 16 runs, 0 skips 128531 decicycles in planar_rgbf32le_to_y, 32 runs, 0 skips 140933 decicycles in planar_rgbf32le_to_y, 64 runs, 0 skips 190980 decicycles in planar_rgbf32be_to_y, 1 runs, 0 skips 176080 decicycles in planar_rgbf32be_to_y, 2 runs, 0 skips 167980 decicycles in planar_rgbf32be_to_y, 4 runs, 0 skips 164685 decicycles in planar_rgbf32be_to_y, 8 runs, 0 skips 162751 decicycles in planar_rgbf32be_to_y, 16 runs, 0 skips 162404 decicycles in planar_rgbf32be_to_y, 32 runs, 0 skips 167849 decicycles in planar_rgbf32be_to_y, 64 runs, 0 skips new timings 183320 decicycles in planar_rgbf32le_to_uv, 1 runs, 0 skips 175700 decicycles in planar_rgbf32le_to_uv, 2 runs, 0 skips 179570 decicycles in planar_rgbf32le_to_uv, 4 runs, 0 skips 172932 decicycles in planar_rgbf32le_to_uv, 8 runs, 0 skips 168707 decicycles in planar_rgbf32le_to_uv, 16 runs, 0 skips 165224 decicycles in planar_rgbf32le_to_uv, 32 runs, 0 skips 163423 decicycles in planar_rgbf32le_to_uv, 64 runs, 0 skips 184940 decicycles in planar_rgbf32be_to_uv, 1 runs, 0 skips 185150 decicycles in planar_rgbf32be_to_uv, 2 runs, 0 skips 185790 decicycles in planar_rgbf32be_to_uv, 4 runs, 0 skips 185472 decicycles in planar_rgbf32be_to_uv, 8 runs, 0 skips 185277 decicycles in planar_rgbf32be_to_uv, 16 runs, 0 skips 185813 decicycles in planar_rgbf32be_to_uv, 32 runs, 0 skips 185332 decicycles in planar_rgbf32be_to_uv, 64 runs, 0 skips 145400 decicycles in planar_rgbf32le_to_y, 1 runs, 0 skips 145100 decicycles in planar_rgbf32le_to_y, 2 runs, 0 skips 143490 decicycles in planar_rgbf32le_to_y, 4 runs, 0 skips 136687 decicycles in planar_rgbf32le_to_y, 8 runs, 0 skips 131271 decicycles in planar_rgbf32le_to_y, 16 runs, 0 skips 128698 decicycles in planar_rgbf32le_to_y, 32 runs, 0 skips 127170 decicycles in planar_rgbf32le_to_y, 64 runs, 0 skips 156020 decicycles in planar_rgbf32be_to_y, 1 runs, 0 skips 146990 decicycles in planar_rgbf32be_to_y, 2 runs, 0 skips 142020 decicycles in planar_rgbf32be_to_y, 4 runs, 0 skips 141052 decicycles in planar_rgbf32be_to_y, 8 runs, 0 skips 138973 decicycles in planar_rgbf32be_to_y, 16 runs, 0 skips 138027 decicycles in planar_rgbf32be_to_y, 32 runs, 0 skips 143939 decicycles in planar_rgbf32be_to_y, 64 runs, 0 skips Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libswscale/input.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libswscale/input.c b/libswscale/input.c index 90efdd2ffc..1351ea5bd4 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -973,7 +973,7 @@ static av_always_inline void planar_rgbf32_to_a(uint8_t *_dst, const uint8_t *_s uint16_t *dst = (uint16_t *)_dst; for (i = 0; i < width; i++) { - dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src[3] + i))); + dst[i] = lrintf(av_clipf(65535.0f * rdpx(src[3] + i), 0.0f, 65535.0f)); } } @@ -987,9 +987,9 @@ static av_always_inline void planar_rgbf32_to_uv(uint8_t *_dstU, uint8_t *_dstV, int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX]; for (i = 0; i < width; i++) { - int g = av_clip_uint16(lrintf(65535.0f * rdpx(src[0] + i))); - int b = av_clip_uint16(lrintf(65535.0f * rdpx(src[1] + i))); - int r = av_clip_uint16(lrintf(65535.0f * rdpx(src[2] + i))); + int g = lrintf(av_clipf(65535.0f * rdpx(src[0] + i), 0.0f, 65535.0f)); + int b = lrintf(av_clipf(65535.0f * rdpx(src[1] + i), 0.0f, 65535.0f)); + int r = lrintf(av_clipf(65535.0f * rdpx(src[2] + i), 0.0f, 65535.0f)); dstU[i] = (ru*r + gu*g + bu*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; dstV[i] = (rv*r + gv*g + bv*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; @@ -1005,9 +1005,9 @@ static av_always_inline void planar_rgbf32_to_y(uint8_t *_dst, const uint8_t *_s int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX]; for (i = 0; i < width; i++) { - int g = av_clip_uint16(lrintf(65535.0f * rdpx(src[0] + i))); - int b = av_clip_uint16(lrintf(65535.0f * rdpx(src[1] + i))); - int r = av_clip_uint16(lrintf(65535.0f * rdpx(src[2] + i))); + int g = lrintf(av_clipf(65535.0f * rdpx(src[0] + i), 0.0f, 65535.0f)); + int b = lrintf(av_clipf(65535.0f * rdpx(src[1] + i), 0.0f, 65535.0f)); + int r = lrintf(av_clipf(65535.0f * rdpx(src[2] + i), 0.0f, 65535.0f)); dst[i] = (ry*r + gy*g + by*b + (0x2001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; } @@ -1021,7 +1021,7 @@ static av_always_inline void grayf32ToY16_c(uint8_t *_dst, const uint8_t *_src, uint16_t *dst = (uint16_t *)_dst; for (i = 0; i < width; ++i){ - dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src + i))); + dst[i] = lrintf(av_clipf(65535.0f * rdpx(src + i), 0.0f, 65535.0f)); } } From 5fc935c7fa6ee943a05b0624ab60a4e3aff4874a Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Tue, 16 Nov 2021 15:35:24 +0800 Subject: [PATCH 165/894] libavfilter: add a gblur_vulkan filter This commit adds a powerful and customizable gblur Vulkan filter, which provides a maximum 127x127 kernel size of Gaussian Filter. The size could be adjusted by requirements on quality or performance. The following command is on how to apply gblur_vulkan filter: ffmpeg -init_hw_device vulkan -i input.264 -vf hwupload=extra_hw_frames=16,gblur_vulkan,hwdownload,format=yuv420p output.264 Signed-off-by: Wu Jianhua --- configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_gblur_vulkan.c | 524 ++++++++++++++++++++++++++++++++++ 4 files changed, 527 insertions(+) create mode 100644 libavfilter/vf_gblur_vulkan.c diff --git a/configure b/configure index 891824757b..1b47f6512d 100755 --- a/configure +++ b/configure @@ -3613,6 +3613,7 @@ frei0r_deps_any="libdl LoadLibrary" frei0r_filter_deps="frei0r" frei0r_src_filter_deps="frei0r" fspp_filter_deps="gpl" +gblur_vulkan_filter_deps="vulkan libglslang" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index e2059766b0..08edc92d8c 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -289,6 +289,7 @@ OBJS-$(CONFIG_FREEZEFRAMES_FILTER) += vf_freezeframes.o OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o OBJS-$(CONFIG_FSPP_FILTER) += vf_fspp.o qp_table.o OBJS-$(CONFIG_GBLUR_FILTER) += vf_gblur.o +OBJS-$(CONFIG_GBLUR_VULKAN_FILTER) += vf_gblur_vulkan.o vulkan.o OBJS-$(CONFIG_GEQ_FILTER) += vf_geq.o OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o OBJS-$(CONFIG_GRAPHMONITOR_FILTER) += f_graphmonitor.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index be94249024..f250020159 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -274,6 +274,7 @@ extern const AVFilter ff_vf_freezeframes; extern const AVFilter ff_vf_frei0r; extern const AVFilter ff_vf_fspp; extern const AVFilter ff_vf_gblur; +extern const AVFilter ff_vf_gblur_vulkan; extern const AVFilter ff_vf_geq; extern const AVFilter ff_vf_gradfun; extern const AVFilter ff_vf_graphmonitor; diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c new file mode 100644 index 0000000000..b9e2c4fbc7 --- /dev/null +++ b/libavfilter/vf_gblur_vulkan.c @@ -0,0 +1,524 @@ +/* + * copyright (c) 2021 Wu Jianhua + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/random_seed.h" +#include "libavutil/opt.h" +#include "vulkan.h" +#include "internal.h" + +#define CGS 32 +#define GBLUR_MAX_KERNEL_SIZE 127 + +typedef struct GBlurVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl_hor; + FFVulkanPipeline *pl_ver; + FFVkBuffer params_buf_hor; + FFVkBuffer params_buf_ver; + + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo tmp_images[3]; + VkDescriptorImageInfo output_images[3]; + VkDescriptorBufferInfo params_desc_hor; + VkDescriptorBufferInfo params_desc_ver; + + int initialized; + int size; + int planes; + int kernel_size; + float sigma; + float sigmaV; + AVFrame *tmpframe; +} GBlurVulkanContext; + +static const char gblur_horizontal[] = { + C(0, void gblur(const ivec2 pos, const int index) ) + C(0, { ) + C(1, vec4 sum = texture(input_image[index], pos) * kernel[0]; ) + C(0, ) + C(1, for(int i = 1; i < kernel.length(); i++) { ) + C(2, sum += texture(input_image[index], pos + vec2(i, 0.0)) * kernel[i]; ) + C(2, sum += texture(input_image[index], pos - vec2(i, 0.0)) * kernel[i]; ) + C(1, } ) + C(0, ) + C(1, imageStore(output_image[index], pos, sum); ) + C(0, } ) +}; + +static const char gblur_vertical[] = { + C(0, void gblur(const ivec2 pos, const int index) ) + C(0, { ) + C(1, vec4 sum = texture(input_image[index], pos) * kernel[0]; ) + C(0, ) + C(1, for(int i = 1; i < kernel.length(); i++) { ) + C(2, sum += texture(input_image[index], pos + vec2(0.0, i)) * kernel[i]; ) + C(2, sum += texture(input_image[index], pos - vec2(0.0, i)) * kernel[i]; ) + C(1, } ) + C(0, ) + C(1, imageStore(output_image[index], pos, sum); ) + C(0, } ) +}; + +static inline float gaussian(float sigma, float x) +{ + return 1.0 / (sqrt(2.0 * M_PI) * sigma) * + exp(-(x * x) / (2.0 * sigma * sigma)); +} + +static inline float gaussian_simpson_integration(float sigma, float a, float b) +{ + return (b - a) * (1.0 / 6.0) * ((gaussian(sigma, a) + + 4.0 * gaussian(sigma, (a + b) * 0.5) + gaussian(sigma, b))); +} + +static void init_gaussian_kernel(float *kernel, float sigma, float kernel_size) +{ + int x; + float sum; + + sum = 0; + for (x = 0; x < kernel_size; x++) { + kernel[x] = gaussian_simpson_integration(sigma, x - 0.5f, x + 0.5f); + if (!x) + sum += kernel[x]; + else + sum += kernel[x] * 2.0; + } + /* Normalized */ + sum = 1.0 / sum; + for (x = 0; x < kernel_size; x++) { + kernel[x] *= sum; + } +} + +static av_cold void init_gaussian_params(GBlurVulkanContext *s) +{ + if (!(s->size & 1)) { + av_log(s, AV_LOG_WARNING, "kernel size should be odd\n"); + s->size++; + } + if (s->sigmaV <= 0) + s->sigmaV = s->sigma; + + s->kernel_size = (s->size >> 1) + 1; + s->tmpframe = NULL; +} + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err; + char *kernel_def; + uint8_t *kernel_mapped; + FFSPIRVShader *shd; + GBlurVulkanContext *s = ctx->priv; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + FFVulkanDescriptorSetBinding image_descs[] = { + { + .name = "input_image", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + { + .name = "output_image", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + }; + + FFVulkanDescriptorSetBinding buf_desc = { + .name = "data", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .mem_layout = "std430", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = NULL, + .buf_content = NULL, + }; + + image_descs[0].sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); + if (!image_descs[0].sampler) + return AVERROR_EXTERNAL; + + init_gaussian_params(s); + + kernel_def = av_asprintf("float kernel[%i];", s->kernel_size); + if (!kernel_def) + return AVERROR(ENOMEM); + + buf_desc.buf_content = kernel_def; + + ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + { /* Create shader for the horizontal pass */ + image_descs[0].updater = s->input_images; + image_descs[1].updater = s->tmp_images; + buf_desc.updater = &s->params_desc_hor; + + s->pl_hor = ff_vk_create_pipeline(ctx, &s->qf); + if (!s->pl_hor) { + err = AVERROR(ENOMEM); + goto fail; + } + + shd = ff_vk_init_shader(ctx, s->pl_hor, "gblur_compute_hor", image_descs[0].stages); + if (!shd) { + err = AVERROR(ENOMEM); + goto fail; + } + + ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 }); + RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, &buf_desc, 1, 0)); + + GLSLD( gblur_horizontal ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_image[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + if (s->planes & (1 << i)) { + GLSLF(2, gblur(pos, %i); ,i); + } else { + GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); + GLSLF(2, imageStore(output_image[%i], pos, res); ,i); + } + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + + RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor)); + RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor)); + + RET(ff_vk_create_buf(ctx, &s->params_buf_hor, sizeof(float) * s->kernel_size, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + RET(ff_vk_map_buffers(ctx, &s->params_buf_hor, &kernel_mapped, 1, 0)); + + init_gaussian_kernel((float *)kernel_mapped, s->sigma, s->kernel_size); + + RET(ff_vk_unmap_buffers(ctx, &s->params_buf_hor, 1, 1)); + + s->params_desc_hor.buffer = s->params_buf_hor.buf; + s->params_desc_hor.range = VK_WHOLE_SIZE; + + ff_vk_update_descriptor_set(ctx, s->pl_hor, 1); + } + + { /* Create shader for the vertical pass */ + image_descs[0].updater = s->tmp_images; + image_descs[1].updater = s->output_images; + buf_desc.updater = &s->params_desc_ver; + + s->pl_ver = ff_vk_create_pipeline(ctx, &s->qf); + if (!s->pl_ver) { + err = AVERROR(ENOMEM); + goto fail; + } + + shd = ff_vk_init_shader(ctx, s->pl_ver, "gblur_compute_ver", image_descs[0].stages); + if (!shd) { + err = AVERROR(ENOMEM); + goto fail; + } + + ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 }); + RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, &buf_desc, 1, 0)); + + GLSLD( gblur_vertical ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_image[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + if (s->planes & (1 << i)) { + GLSLF(2, gblur(pos, %i); ,i); + } else { + GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); + GLSLF(2, imageStore(output_image[%i], pos, res); ,i); + } + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + + RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver)); + RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver)); + + RET(ff_vk_create_buf(ctx, &s->params_buf_ver, sizeof(float) * s->kernel_size, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + RET(ff_vk_map_buffers(ctx, &s->params_buf_ver, &kernel_mapped, 1, 0)); + + init_gaussian_kernel((float *)kernel_mapped, s->sigmaV, s->kernel_size); + + RET(ff_vk_unmap_buffers(ctx, &s->params_buf_ver, 1, 1)); + + s->params_desc_ver.buffer = s->params_buf_ver.buf; + s->params_desc_ver.range = VK_WHOLE_SIZE; + + ff_vk_update_descriptor_set(ctx, s->pl_ver, 1); + } + + RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); + + s->initialized = 1; + + return 0; + +fail: + av_free(kernel_def); + return err; +} + +static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx) +{ + GBlurVulkanContext *s = avctx->priv; + + av_frame_free(&s->tmpframe); + + ff_vk_filter_uninit(avctx); + ff_vk_free_buf(avctx, &s->params_buf_hor); + ff_vk_free_buf(avctx, &s->params_buf_ver); + + s->initialized = 0; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe) +{ + int err; + VkCommandBuffer cmd_buf; + + const VkFormat *input_formats = NULL; + const VkFormat *output_formats = NULL; + GBlurVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkctx.vkfn; + AVVkFrame *in = (AVVkFrame *)inframe->data[0]; + AVVkFrame *tmp = (AVVkFrame *)s->tmpframe->data[0]; + AVVkFrame *out = (AVVkFrame *)outframe->data[0]; + + int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + ff_vk_start_exec_recording(avctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + + input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + for (int i = 0; i < planes; i++) { + RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView, + in->img[i], + input_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView, + tmp->img[i], + output_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, + out->img[i], + output_formats[i], + ff_comp_identity_map)); + + s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->tmp_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + ff_vk_update_descriptor_set(avctx, s->pl_hor, 0); + ff_vk_update_descriptor_set(avctx, s->pl_ver, 0); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = in->layout[i], + .newLayout = s->input_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = in->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + .oldLayout = tmp->layout[i], + .newLayout = s->tmp_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = tmp->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, + .oldLayout = out->layout[i], + .newLayout = s->output_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = out->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + }; + + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers); + + in->layout[i] = barriers[0].newLayout; + in->access[i] = barriers[0].dstAccessMask; + + tmp->layout[i] = barriers[1].newLayout; + tmp->access[i] = barriers[1].dstAccessMask; + + out->layout[i] = barriers[2].newLayout; + out->access[i] = barriers[2].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor); + + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); + + ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver); + + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); + + ff_vk_add_exec_dep(avctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(avctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + err = ff_vk_submit_exec_queue(avctx, s->exec); + if (err) + return err; + + ff_vk_qf_rotate(&s->qf); + + return 0; +fail: + ff_vk_discard_exec_deps(avctx, s->exec); + return err; +} + +static int gblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = link->dst; + GBlurVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) { + RET(init_filter(ctx, in)); + s->tmpframe = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!s->tmpframe) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + RET(process_frames(ctx, out, in)); + + RET(av_frame_copy_props(out, in)); + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + av_frame_free(&s->tmpframe); + + return err; +} + +#define OFFSET(x) offsetof(GBlurVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption gblur_vulkan_options[] = { + { "sigma", "Set sigma", OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl = 0.5}, 0.01, 1024.0, FLAGS }, + { "sigmaV", "Set vertical sigma", OFFSET(sigmaV), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0.0, 1024.0, FLAGS }, + { "planes", "Set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 0xF}, 0, 0xF, FLAGS }, + { "size", "Set kernel size", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 19}, 1, GBLUR_MAX_KERNEL_SIZE, FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(gblur_vulkan); + +static const AVFilterPad gblur_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &gblur_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +static const AVFilterPad gblur_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + } +}; + +const AVFilter ff_vf_gblur_vulkan = { + .name = "gblur_vulkan", + .description = NULL_IF_CONFIG_SMALL("Gaussian Blur in Vulkan"), + .priv_size = sizeof(GBlurVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &gblur_vulkan_uninit, + FILTER_INPUTS(gblur_vulkan_inputs), + FILTER_OUTPUTS(gblur_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &gblur_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 8f9888a8d4f5254aba8ab75a352539b3a46a36cb Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 16 Nov 2021 10:22:03 +0100 Subject: [PATCH 166/894] lavfi/vulkan: fix static descriptor set updating Update all descriptor sets for all queues if a descriptor set hasn't been initialized yet. --- libavfilter/vulkan.c | 21 +++++++++++++++++++++ libavfilter/vulkan.h | 1 + 2 files changed, 22 insertions(+) diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index a30699963e..5258e0c3d6 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -1105,6 +1105,13 @@ int ff_vk_add_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, if (!pl->desc_layout) return AVERROR(ENOMEM); + pl->desc_set_initialized = av_realloc_array(pl->desc_set_initialized, + sizeof(*pl->desc_set_initialized), + pl->descriptor_sets_num + 1); + if (!pl->desc_set_initialized) + return AVERROR(ENOMEM); + + pl->desc_set_initialized[pl->descriptor_sets_num] = 0; layout = &pl->desc_layout[pl->desc_layout_num]; { /* Create descriptor set layout descriptions */ @@ -1245,6 +1252,19 @@ void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, FFVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; + /* If a set has never been updated, update all queues' sets. */ + if (!pl->desc_set_initialized[set_id]) { + for (int i = 0; i < pl->qf->nb_queues; i++) { + set_id = set_id*pl->qf->nb_queues + i; + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, + pl->desc_set[set_id], + pl->desc_template[set_id], + s); + } + pl->desc_set_initialized[set_id] = 1; + return; + } + set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue; vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, @@ -1514,6 +1534,7 @@ static void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) av_freep(&pl->shaders); av_freep(&pl->desc_layout); av_freep(&pl->desc_template); + av_freep(&pl->desc_set_initialized); av_freep(&pl->push_consts); pl->push_consts_num = 0; diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index 9d17d2b14f..df8abf9e30 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -113,6 +113,7 @@ typedef struct FFVulkanPipeline { void **desc_staging; VkDescriptorSetLayoutBinding **desc_binding; VkDescriptorUpdateTemplate *desc_template; + int *desc_set_initialized; int desc_layout_num; int descriptor_sets_num; int total_descriptor_sets; From 8af7bcb6c3282d3911f9d5553e7f86da0fc3d160 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 16 Nov 2021 10:28:27 +0100 Subject: [PATCH 167/894] lavfi/vulkan: add mutliqueue emulation code This helps with testing multiple queues when the hardware only has a single queue. --- libavfilter/vulkan.c | 33 ++++++++++++++++++--------------- libavfilter/vulkan.h | 7 ++++--- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index 5258e0c3d6..3bb4eea7a1 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -90,38 +90,40 @@ const char *ff_vk_ret2str(VkResult res) } void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int queue_limit) + VkQueueFlagBits dev_family, int nb_queues) { FFVulkanContext *s = avctx->priv; - if (!queue_limit) - queue_limit = INT32_MAX; - switch (dev_family) { case VK_QUEUE_GRAPHICS_BIT: qf->queue_family = s->hwctx->queue_family_index; - qf->nb_queues = FFMIN(s->hwctx->nb_graphics_queues, queue_limit); - return; + qf->actual_queues = s->hwctx->nb_graphics_queues; + break; case VK_QUEUE_COMPUTE_BIT: qf->queue_family = s->hwctx->queue_family_comp_index; - qf->nb_queues = FFMIN(s->hwctx->nb_comp_queues, queue_limit); - return; + qf->actual_queues = s->hwctx->nb_comp_queues; + break; case VK_QUEUE_TRANSFER_BIT: qf->queue_family = s->hwctx->queue_family_tx_index; - qf->nb_queues = FFMIN(s->hwctx->nb_tx_queues, queue_limit); - return; + qf->actual_queues = s->hwctx->nb_tx_queues; + break; case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: qf->queue_family = s->hwctx->queue_family_encode_index; - qf->nb_queues = FFMIN(s->hwctx->nb_encode_queues, queue_limit); - return; + qf->actual_queues = s->hwctx->nb_encode_queues; + break; case VK_QUEUE_VIDEO_DECODE_BIT_KHR: qf->queue_family = s->hwctx->queue_family_decode_index; - qf->nb_queues = FFMIN(s->hwctx->nb_decode_queues, queue_limit); - return; + qf->actual_queues = s->hwctx->nb_decode_queues; + break; default: av_assert0(0); /* Should never happen */ } + if (qf->actual_queues) + qf->nb_queues = qf->actual_queues; + else + qf->nb_queues = nb_queues; + return; } @@ -435,7 +437,8 @@ int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx, for (int i = 0; i < qf->nb_queues; i++) { FFVkQueueCtx *q = &e->queues[i]; - vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, i, &q->queue); + vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, + i % qf->actual_queues, &q->queue); } *ctx = e; diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index df8abf9e30..df0e830af8 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -87,6 +87,7 @@ typedef struct FFVkQueueFamilyCtx { int queue_family; int nb_queues; int cur_queue; + int actual_queues; } FFVkQueueFamilyCtx; typedef struct FFVulkanPipeline { @@ -235,11 +236,11 @@ int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); /** - * Initialize a queue family. - * A queue limit of 0 means no limit. + * Initialize a queue family with a specific number of queues. + * If nb_queues == 0, use however many queues the queue family has. */ void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int queue_limit); + VkQueueFlagBits dev_family, int nb_queues); /** * Rotate through the queues in a queue family. From 85433fb937f8ef69077a05a03c347ada46281282 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 Nov 2021 13:40:37 +0100 Subject: [PATCH 168/894] lavf: improve AV_DISPOSITION_* doxy Also switch the values definition to the (1 << N) style, which is easier to read. --- libavformat/avformat.h | 96 +++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 19 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a2af7e9f89..c38fac5a37 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -803,22 +803,56 @@ typedef struct AVIndexEntry { int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ } AVIndexEntry; -#define AV_DISPOSITION_DEFAULT 0x0001 -#define AV_DISPOSITION_DUB 0x0002 -#define AV_DISPOSITION_ORIGINAL 0x0004 -#define AV_DISPOSITION_COMMENT 0x0008 -#define AV_DISPOSITION_LYRICS 0x0010 -#define AV_DISPOSITION_KARAOKE 0x0020 +/** + * The stream should be chosen by default among other streams of the same type, + * unless the user has explicitly specified otherwise. + */ +#define AV_DISPOSITION_DEFAULT (1 << 0) +/** + * The stream is not in original language. + * + * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most + * one of them should be set in properly tagged streams. + * @note This disposition may apply to any stream type, not just audio. + */ +#define AV_DISPOSITION_DUB (1 << 1) +/** + * The stream is in original language. + * + * @see the notes for AV_DISPOSITION_DUB + */ +#define AV_DISPOSITION_ORIGINAL (1 << 2) +/** + * The stream is a commentary track. + */ +#define AV_DISPOSITION_COMMENT (1 << 3) +/** + * The stream contains song lyrics. + */ +#define AV_DISPOSITION_LYRICS (1 << 4) +/** + * The stream contains karaoke audio. + */ +#define AV_DISPOSITION_KARAOKE (1 << 5) /** * Track should be used during playback by default. * Useful for subtitle track that should be displayed * even when user did not explicitly ask for subtitles. */ -#define AV_DISPOSITION_FORCED 0x0040 -#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */ -#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */ -#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */ +#define AV_DISPOSITION_FORCED (1 << 6) +/** + * The stream is intended for hearing impaired audiences. + */ +#define AV_DISPOSITION_HEARING_IMPAIRED (1 << 7) +/** + * The stream is intended for visually impaired audiences. + */ +#define AV_DISPOSITION_VISUAL_IMPAIRED (1 << 8) +/** + * The audio stream contains music and sound effects without voice. + */ +#define AV_DISPOSITION_CLEAN_EFFECTS (1 << 9) /** * The stream is stored in the file as an attached picture/"cover art" (e.g. * APIC frame in ID3v2). The first (usually only) packet associated with it @@ -826,21 +860,39 @@ typedef struct AVIndexEntry { * seeking takes place. It can also be accessed at any time in * AVStream.attached_pic. */ -#define AV_DISPOSITION_ATTACHED_PIC 0x0400 +#define AV_DISPOSITION_ATTACHED_PIC (1 << 10) /** * The stream is sparse, and contains thumbnail images, often corresponding * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. */ -#define AV_DISPOSITION_TIMED_THUMBNAILS 0x0800 +#define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) /** - * To specify text track kind (different from subtitles default). + * The subtitle stream contains captions, providing a transcription and possibly + * a translation of audio. Typically intended for hearing-impaired audiences. */ -#define AV_DISPOSITION_CAPTIONS 0x10000 -#define AV_DISPOSITION_DESCRIPTIONS 0x20000 -#define AV_DISPOSITION_METADATA 0x40000 -#define AV_DISPOSITION_DEPENDENT 0x80000 ///< dependent audio stream (mix_type=0 in mpegts) -#define AV_DISPOSITION_STILL_IMAGE 0x100000 ///< still images in video stream (still_picture_flag=1 in mpegts) +#define AV_DISPOSITION_CAPTIONS (1 << 16) +/** + * The subtitle stream contains a textual description of the video content. + * Typically intended for visually-impaired audiences or for the cases where the + * video cannot be seen. + */ +#define AV_DISPOSITION_DESCRIPTIONS (1 << 17) +/** + * The subtitle stream contains time-aligned metadata that is not intended to be + * directly presented to the user. + */ +#define AV_DISPOSITION_METADATA (1 << 18) +/** + * The audio stream is intended to be mixed with another stream before + * presentation. + * Corresponds to mix_type=0 in mpegts. + */ +#define AV_DISPOSITION_DEPENDENT (1 << 19) +/** + * The video stream contains still images. + */ +#define AV_DISPOSITION_STILL_IMAGE (1 << 20) /** * Options for behavior on timestamp wrap detection. @@ -903,7 +955,13 @@ typedef struct AVStream { int64_t nb_frames; ///< number of frames in this stream if known or 0 - int disposition; /**< AV_DISPOSITION_* bit field */ + /** + * Stream disposition - a combination of AV_DISPOSITION_* flags. + * - demuxing: set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. From ed75a08d36c011db152d89e2c23b2dab55331d93 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 14:50:00 +0100 Subject: [PATCH 169/894] lavf: add an AVClass to AVStream on next major bump Also add a function to retrieve that class, analogously to avformat_get_class(). This will be useful for adding an AVOption for dispositions. --- doc/APIchanges | 4 ++++ libavformat/avformat.h | 15 +++++++++++++++ libavformat/utils.c | 15 +++++++++++++++ libavformat/version.h | 3 ++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 10bad1d21e..a86f4b936e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,10 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-11-xx - xxxxxxxxxx - lavf 59.9.100 - avformat.h + Add av_stream_get_class(). Schedule adding AVStream.av_class at libavformat + major version 60. + 2021-11-12 - xxxxxxxxxx - lavu 57.8.100 - hwcontext_vulkan.h Added AVFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, nb_encode_queues, queue_family_decode_index, and nb_decode_queues. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index c38fac5a37..da92a3847a 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -909,6 +909,13 @@ typedef struct AVIndexEntry { * sizeof(AVStream) must not be used outside libav*. */ typedef struct AVStream { +#if FF_API_AVSTREAM_CLASS + /** + * A class for @ref avoptions. Set on stream creation. + */ + const AVClass *av_class; +#endif + int index; /**< stream index in AVFormatContext */ /** * Format-specific stream ID. @@ -1864,6 +1871,14 @@ void avformat_free_context(AVFormatContext *s); */ const AVClass *avformat_get_class(void); +/** + * Get the AVClass for AVStream. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_get_class(void); + /** * Add a new stream to a media file. * diff --git a/libavformat/utils.c b/libavformat/utils.c index bbc61dccbb..dcfbae7d7e 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -721,6 +721,17 @@ void avformat_free_context(AVFormatContext *s) av_free(s); } +static const AVClass stream_class = { + .class_name = "AVStream", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVClass *av_stream_get_class(void) +{ + return &stream_class; +} + AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) { FFFormatContext *const si = ffformatcontext(s); @@ -745,6 +756,10 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) return NULL; st = &sti->pub; +#if FF_API_AVSTREAM_CLASS + st->av_class = &stream_class; +#endif + st->codecpar = avcodec_parameters_alloc(); if (!st->codecpar) goto fail; diff --git a/libavformat/version.h b/libavformat/version.h index 2e860b8d76..1d10481734 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 8 +#define LIBAVFORMAT_VERSION_MINOR 9 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -58,6 +58,7 @@ #define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) #define FF_API_R_FRAME_RATE 1 From b731fb5104d06ddbfa6e61ea9451ba77c1c22bce Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 Nov 2021 14:35:13 +0100 Subject: [PATCH 170/894] lavf: add public functions converting dispositions to/from strings --- doc/APIchanges | 1 + libavformat/avformat.h | 14 +++++++++++++ libavformat/utils.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index a86f4b936e..53f229d41a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -17,6 +17,7 @@ API changes, most recent first: 2021-11-xx - xxxxxxxxxx - lavf 59.9.100 - avformat.h Add av_stream_get_class(). Schedule adding AVStream.av_class at libavformat major version 60. + Add av_disposition_to_string() and av_disposition_from_string(). 2021-11-12 - xxxxxxxxxx - lavu 57.8.100 - hwcontext_vulkan.h Added AVFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, diff --git a/libavformat/avformat.h b/libavformat/avformat.h index da92a3847a..0343825aa0 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -894,6 +894,20 @@ typedef struct AVIndexEntry { */ #define AV_DISPOSITION_STILL_IMAGE (1 << 20) +/** + * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error + * code if disp does not correspond to a known stream disposition. + */ +int av_disposition_from_string(const char *disp); + +/** + * @param disposition a combination of AV_DISPOSITION_* values + * @return The string description corresponding to the lowest set bit in + * disposition. NULL when the lowest set bit does not correspond + * to a known disposition or when disposition is 0. + */ +const char *av_disposition_to_string(int disposition); + /** * Options for behavior on timestamp wrap detection. */ diff --git a/libavformat/utils.c b/libavformat/utils.c index dcfbae7d7e..55bc7e2019 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -28,6 +28,7 @@ #include "libavutil/bprint.h" #include "libavutil/dict.h" #include "libavutil/internal.h" +#include "libavutil/intmath.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "libavutil/pixfmt.h" @@ -1965,3 +1966,49 @@ void ff_format_set_url(AVFormatContext *s, char *url) av_freep(&s->url); s->url = url; } + +static const struct { + const char *str; + int disposition; +} dispositions[] = { + { "default", AV_DISPOSITION_DEFAULT }, + { "dub", AV_DISPOSITION_DUB }, + { "original", AV_DISPOSITION_ORIGINAL }, + { "comment", AV_DISPOSITION_COMMENT }, + { "lyrics", AV_DISPOSITION_LYRICS }, + { "karaoke", AV_DISPOSITION_KARAOKE }, + { "forced", AV_DISPOSITION_FORCED }, + { "hearing_impaired", AV_DISPOSITION_HEARING_IMPAIRED }, + { "visual_impaired", AV_DISPOSITION_VISUAL_IMPAIRED }, + { "clean_effects", AV_DISPOSITION_CLEAN_EFFECTS }, + { "attached_pic", AV_DISPOSITION_ATTACHED_PIC }, + { "timed_thumbnails", AV_DISPOSITION_TIMED_THUMBNAILS }, + { "captions", AV_DISPOSITION_CAPTIONS }, + { "descriptions", AV_DISPOSITION_DESCRIPTIONS }, + { "metadata", AV_DISPOSITION_METADATA }, + { "dependent", AV_DISPOSITION_DEPENDENT }, + { "still_image", AV_DISPOSITION_STILL_IMAGE }, +}; + +int av_disposition_from_string(const char *disp) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(dispositions); i++) + if (!strcmp(disp, dispositions[i].str)) + return dispositions[i].disposition; + return AVERROR(EINVAL); +} + +const char *av_disposition_to_string(int disposition) +{ + int val; + + if (disposition <= 0) + return NULL; + + val = 1 << ff_ctz(disposition); + for (int i = 0; i < FF_ARRAY_ELEMS(dispositions); i++) + if (dispositions[i].disposition == val) + return dispositions[i].str; + + return NULL; +} From a4c5d241ec215cfa680c5fa706377e40d18e8040 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 15:15:07 +0100 Subject: [PATCH 171/894] lavf: add "disposition" AVOption to AVStream AVClass Use it to remove custom disposition parsing code from ffmpeg.c --- doc/APIchanges | 1 + fftools/ffmpeg.c | 38 +++++++++++--------------------------- libavformat/utils.c | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 53f229d41a..ad57ae29d6 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -18,6 +18,7 @@ API changes, most recent first: Add av_stream_get_class(). Schedule adding AVStream.av_class at libavformat major version 60. Add av_disposition_to_string() and av_disposition_from_string(). + Add "disposition" AVOption to AVStream's class. 2021-11-12 - xxxxxxxxxx - lavu 57.8.100 - hwcontext_vulkan.h Added AVFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d141f34df9..65d6a2668d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3665,34 +3665,18 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, // parse user provided disposition, and update stream values if (ost->disposition) { - static const AVOption opts[] = { - { "disposition" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, - { "default" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "flags" }, - { "dub" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "flags" }, - { "original" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "flags" }, - { "comment" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "flags" }, - { "lyrics" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "flags" }, - { "karaoke" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "flags" }, - { "forced" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "flags" }, - { "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" }, - { "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" }, - { "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" }, - { "attached_pic" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "flags" }, - { "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" }, - { "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" }, - { "dependent" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "flags" }, - { "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" }, - { NULL }, - }; - static const AVClass class = { - .class_name = "", - .item_name = av_default_item_name, - .option = opts, - .version = LIBAVUTIL_VERSION_INT, - }; - const AVClass *pclass = &class; +#if LIBAVFORMAT_VERSION_MAJOR >= 60 + ret = av_opt_set(ost->st, "disposition", ost->disposition, 0); +#else + { + const AVClass *class = av_stream_get_class(); + const AVOption *o = av_opt_find(&class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); + + av_assert0(o); + ret = av_opt_eval_flags(&class, o, ost->disposition, &ost->st->disposition); + } +#endif - ret = av_opt_eval_flags(&pclass, &opts[0], ost->disposition, &ost->st->disposition); if (ret < 0) return ret; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 55bc7e2019..a8611f5877 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -722,10 +722,34 @@ void avformat_free_context(AVFormatContext *s) av_free(s); } +static const AVOption stream_options[] = { + { "disposition", NULL, offsetof(AVStream, disposition), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, + .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "disposition" }, + { "default", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "disposition" }, + { "dub", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "disposition" }, + { "original", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "disposition" }, + { "comment", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "disposition" }, + { "lyrics", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "disposition" }, + { "karaoke", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "disposition" }, + { "forced", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "disposition" }, + { "hearing_impaired", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "disposition" }, + { "visual_impaired", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "disposition" }, + { "clean_effects", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "disposition" }, + { "attached_pic", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "disposition" }, + { "timed_thumbnails", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_TIMED_THUMBNAILS }, .unit = "disposition" }, + { "captions", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "disposition" }, + { "descriptions", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "disposition" }, + { "metadata", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "disposition" }, + { "dependent", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "disposition" }, + { "still_image", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_STILL_IMAGE }, .unit = "disposition" }, + { NULL } +}; + static const AVClass stream_class = { .class_name = "AVStream", .item_name = av_default_item_name, .version = LIBAVUTIL_VERSION_INT, + .option = stream_options, }; const AVClass *av_stream_get_class(void) From d4ae2a20e8783a3658d47bae952ae681c6465a39 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 17:05:56 +0100 Subject: [PATCH 172/894] cmdutils: add an option for listing stream dispositions --- doc/fftools-common-opts.texi | 3 +++ fftools/cmdutils.c | 10 ++++++++++ fftools/cmdutils.h | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 7643dd8396..d9145704d6 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -167,6 +167,9 @@ Show available sample formats. @item -layouts Show channel names and standard channel layouts. +@item -dispositions +Show stream dispositions. + @item -colors Show recognized color names. diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 426ba6c99f..594eeef379 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1820,6 +1820,16 @@ int show_sample_fmts(void *optctx, const char *opt, const char *arg) return 0; } +int show_dispositions(void *optctx, const char *opt, const char *arg) +{ + for (int i = 0; i < 32; i++) { + const char *str = av_disposition_to_string(1 << i); + if (str) + printf("%s\n", str); + } + return 0; +} + static void show_help_codec(const char *name, int encoder) { const AVCodecDescriptor *desc; diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 30f0b79725..64dd7266bc 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -238,6 +238,7 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags, { "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \ { "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \ { "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \ + { "dispositions", OPT_EXIT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \ { "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \ { "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ { "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ @@ -577,6 +578,11 @@ int show_layouts(void *optctx, const char *opt, const char *arg); */ int show_sample_fmts(void *optctx, const char *opt, const char *arg); +/** + * Print a listing containing all supported stream dispositions. + */ +int show_dispositions(void *optctx, const char *opt, const char *arg); + /** * Print a listing containing all the color names and values recognized * by the program. From bd55552d692254b53504357c6987eea976cff4f9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 17:22:57 +0100 Subject: [PATCH 173/894] ffmpeg: rewrite setting the stream disposition Currently, the code doing this is spread over several places and may behave in unexpected ways. E.g. automatic 'default' marking is only done for streams fed by complex filtergraphs. It is also applied in the order in which the output streams are initialized, which is effectively random. Move processing the dispositions at the end of open_output_file(), when we already have all the necessary information. Apply the automatic default marking only if no explicit -disposition options were supplied by the user, and apply it to the first stream of each type (excluding attached pics) when there is more than one stream of that type and no default markings were copied from the input streams. Explicitly document the new behavior. Changes the results of some tests, where the output file gets a default disposition, while it previously did not. --- doc/ffmpeg.texi | 35 ++++----- fftools/ffmpeg.c | 35 +-------- fftools/ffmpeg_opt.c | 72 +++++++++++++++++++ tests/ref/fate/ffprobe_compact | 60 ++++++++-------- tests/ref/fate/ffprobe_csv | 60 ++++++++-------- tests/ref/fate/ffprobe_default | 62 ++++++++-------- tests/ref/fate/ffprobe_flat | 62 ++++++++-------- tests/ref/fate/ffprobe_ini | 62 ++++++++-------- tests/ref/fate/ffprobe_json | 62 ++++++++-------- tests/ref/fate/ffprobe_xml | 60 ++++++++-------- tests/ref/fate/ffprobe_xsd | 60 ++++++++-------- .../fate/matroska-mastering-display-metadata | 4 +- 12 files changed, 334 insertions(+), 300 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 62d9703b7a..8418573618 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -560,27 +560,22 @@ ffmpeg -i INPUT -metadata:s:a:0 language=eng OUTPUT @item -disposition[:stream_specifier] @var{value} (@emph{output,per-stream}) Sets the disposition for a stream. -This option overrides the disposition copied from the input stream. It is also -possible to delete the disposition by setting it to 0. +By default, the disposition is copied from the input stream, unless the output +stream this option applies to is fed by a complex filtergraph - in that case the +disposition is unset by default. -The following dispositions are recognized: -@table @option -@item default -@item dub -@item original -@item comment -@item lyrics -@item karaoke -@item forced -@item hearing_impaired -@item visual_impaired -@item clean_effects -@item attached_pic -@item captions -@item descriptions -@item dependent -@item metadata -@end table +@var{value} is a sequence of items separated by '+' or '-'. The first item may +also be prefixed with '+' or '-', in which case this option modifies the default +value. Otherwise (the first item is not prefixed) this options overrides the +default value. A '+' prefix adds the given disposition, '-' removes it. It is +also possible to clear the disposition by setting it to 0. + +If no @code{-disposition} options were specified for an output file, ffmpeg will +automatically set the 'default' disposition on the first stream of each type, +when there are multiple streams of this type in the output file and no stream of +that type is already marked as default. + +The @code{-dispositions} option lists the known dispositions. For example, to make the second audio stream the default stream: @example diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 65d6a2668d..7b2dcee838 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3168,9 +3168,6 @@ static int init_output_stream_streamcopy(OutputStream *ost) if (ost->st->duration <= 0 && ist->st->duration > 0) ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); - // copy disposition - ost->st->disposition = ist->st->disposition; - if (ist->st->nb_side_data) { for (i = 0; i < ist->st->nb_side_data; i++) { const AVPacketSideData *sd_src = &ist->st->side_data[i]; @@ -3358,7 +3355,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *dec_ctx = NULL; AVFormatContext *oc = output_files[ost->file_index]->ctx; - int j, ret; + int ret; set_encoder_id(output_files[ost->file_index], ost); @@ -3368,21 +3365,9 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) av_dict_set(&ost->st->metadata, "rotate", NULL, 0); if (ist) { - ost->st->disposition = ist->st->disposition; - dec_ctx = ist->dec_ctx; enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; - } else { - for (j = 0; j < oc->nb_streams; j++) { - AVStream *st = oc->streams[j]; - if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type) - break; - } - if (j == oc->nb_streams) - if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || - ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - ost->st->disposition = AV_DISPOSITION_DEFAULT; } if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -3663,24 +3648,6 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, return ret; } - // parse user provided disposition, and update stream values - if (ost->disposition) { -#if LIBAVFORMAT_VERSION_MAJOR >= 60 - ret = av_opt_set(ost->st, "disposition", ost->disposition, 0); -#else - { - const AVClass *class = av_stream_get_class(); - const AVOption *o = av_opt_find(&class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); - - av_assert0(o); - ret = av_opt_eval_flags(&class, o, ost->disposition, &ost->st->disposition); - } -#endif - - if (ret < 0) - return ret; - } - /* initialize bitstream filters for the output stream * needs to be done here, because the codec id for streamcopy is not * known until now */ diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index ab4c63a362..4685cf6435 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -2150,6 +2150,72 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) return 0; } +static int set_dispositions(OutputFile *of) +{ + int nb_streams[AVMEDIA_TYPE_NB] = { 0 }; + int have_default[AVMEDIA_TYPE_NB] = { 0 }; + int have_manual = 0; + + // first, copy the input dispositions + for (int i = 0; i< of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + + nb_streams[ost->st->codecpar->codec_type]++; + + have_manual |= !!ost->disposition; + + if (ost->source_index >= 0) { + ost->st->disposition = input_streams[ost->source_index]->st->disposition; + + if (ost->st->disposition & AV_DISPOSITION_DEFAULT) + have_default[ost->st->codecpar->codec_type] = 1; + } + } + + if (have_manual) { + // process manually set dispositions - they override the above copy + for (int i = 0; i< of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + int ret; + + if (!ost->disposition) + continue; + +#if LIBAVFORMAT_VERSION_MAJOR >= 60 + ret = av_opt_set(ost->st, "disposition", ost->disposition, 0); +#else + { + const AVClass *class = av_stream_get_class(); + const AVOption *o = av_opt_find(&class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); + + av_assert0(o); + ret = av_opt_eval_flags(&class, o, ost->disposition, &ost->st->disposition); + } +#endif + + if (ret < 0) + return ret; + } + } else { + // For each media type with more than one stream, find a suitable stream to + // mark as default, unless one is already marked default. + // "Suitable" means the first of that type, skipping attached pictures. + for (int i = 0; i< of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + if (nb_streams[type] < 2 || have_default[type] || + ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) + continue; + + ost->st->disposition |= AV_DISPOSITION_DEFAULT; + have_default[type] = 1; + } + } + + return 0; +} + static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, AVFormatContext *oc) { @@ -2857,6 +2923,12 @@ loop_end: } } + err = set_dispositions(of); + if (err < 0) { + av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n"); + exit_program(1); + } + return 0; } diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact index 12565d2600..911777069a 100644 --- a/tests/ref/fate/ffprobe_compact +++ b/tests/ref/fate/ffprobe_compact @@ -1,32 +1,32 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=2048|pos=647|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=647|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=230400|pos=2722|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=2722|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=30000|pos=233143|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=233143|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|size=2048|pos=263148|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=1024|pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263148|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=230400|pos=265226|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265226|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=30000|pos=495650|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495650|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|size=2048|pos=525655|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=2048|pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525655|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|size=2048|pos=527726|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=3072|pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527726|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=230400|pos=529804|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529804|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=30000|pos=760228|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760228|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|size=2048|pos=790233|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=4096|pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790233|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=393|duration_time=0.008912|size=786|pos=792304|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=5120|pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=393|pkt_duration_time=0.008912|pkt_pos=792304|pkt_size=786|sample_fmt=s16|nb_samples=393|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=230400|pos=793120|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=793120|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=30000|pos=1023544|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1023544|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=2048|pos=669|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=669|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=230400|pos=2744|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=2744|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=30000|pos=233165|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=233165|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|size=2048|pos=263170|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=1024|pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263170|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=230400|pos=265248|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265248|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=30000|pos=495672|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495672|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|size=2048|pos=525677|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=2048|pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525677|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|size=2048|pos=527748|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=3072|pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527748|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=230400|pos=529826|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529826|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=30000|pos=760250|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760250|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|size=2048|pos=790255|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=4096|pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790255|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=393|duration_time=0.008912|size=786|pos=792326|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=5120|pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=393|pkt_duration_time=0.008912|pkt_pos=792326|pkt_size=786|sample_fmt=s16|nb_samples=393|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=230400|pos=793142|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=793142|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=30000|pos=1023566|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1023566|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_tag_string=PSD[16]|codec_tag=0x10445350|sample_fmt=s16|sample_rate=44100|channels=1|channel_layout=unknown|bits_per_sample=16|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/44100|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=705600|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=6|nb_read_packets=6|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:E=mc²|tag:encoder=Lavc pcm_s16le -stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo +stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|coded_width=100|coded_height=100|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:encoder=Lavc rawvideo -format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1053624|bit_rate=70241600|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': |tag:comment2=I ♥ Üñîçød€ +format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1053646|bit_rate=70243066|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': |tag:comment2=I ♥ Üñîçød€ diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv index 0bbc15e4d5..fd6bb242c9 100644 --- a/tests/ref/fate/ffprobe_csv +++ b/tests/ref/fate/ffprobe_csv @@ -1,32 +1,32 @@ -packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,2048,647,K_ -frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,647,2048,s16,1024,1,unknown -packet,video,1,0,0.000000,0,0.000000,2048,0.040000,230400,2722,K_ -frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2722,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,0,0.000000,0,0.000000,2048,0.040000,30000,233143,K_ -frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233143,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,2048,263148,K_ -frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263148,2048,s16,1024,1,unknown -packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,230400,265226,K_ -frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265226,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,30000,495650,K_ -frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495650,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,2048,525655,K_ -frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525655,2048,s16,1024,1,unknown -packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,2048,527726,K_ -frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527726,2048,s16,1024,1,unknown -packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,230400,529804,K_ -frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529804,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,30000,760228,K_ -frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760228,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,2048,790233,K_ -frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790233,2048,s16,1024,1,unknown -packet,audio,0,5120,0.116100,5120,0.116100,393,0.008912,786,792304,K_ -frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,393,0.008912,792304,786,s16,393,1,unknown -packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,230400,793120,K_ -frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,793120,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,30000,1023544,K_ -frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1023544,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,2048,669,K_ +frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,669,2048,s16,1024,1,unknown +packet,video,1,0,0.000000,0,0.000000,2048,0.040000,230400,2744,K_ +frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2744,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,0,0.000000,0,0.000000,2048,0.040000,30000,233165,K_ +frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233165,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,2048,263170,K_ +frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263170,2048,s16,1024,1,unknown +packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,230400,265248,K_ +frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265248,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,30000,495672,K_ +frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495672,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,2048,525677,K_ +frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525677,2048,s16,1024,1,unknown +packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,2048,527748,K_ +frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527748,2048,s16,1024,1,unknown +packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,230400,529826,K_ +frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529826,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,30000,760250,K_ +frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760250,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,2048,790255,K_ +frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790255,2048,s16,1024,1,unknown +packet,audio,0,5120,0.116100,5120,0.116100,393,0.008912,786,792326,K_ +frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,393,0.008912,792326,786,s16,393,1,unknown +packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,230400,793142,K_ +frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,793142,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,30000,1023566,K_ +frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1023566,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified stream,0,pcm_s16le,unknown,audio,PSD[16],0x10445350,s16,44100,1,unknown,16,N/A,0/0,0/0,1/44100,0,0.000000,N/A,N/A,705600,N/A,N/A,N/A,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,mc²,Lavc pcm_s16le -stream,1,rawvideo,unknown,video,RGB[24],0x18424752,320,240,320,240,0,0,0,1:1,4:3,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo +stream,1,rawvideo,unknown,video,RGB[24],0x18424752,320,240,320,240,0,0,0,1:1,4:3,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo stream,2,rawvideo,unknown,video,RGB[24],0x18424752,100,100,100,100,0,0,0,1:1,1:1,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo -format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1053624,70241600,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': ",I ♥ Üñîçød€ +format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1053646,70243066,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': ",I ♥ Üñîçød€ diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default index 54e992c406..d3d90fa5d6 100644 --- a/tests/ref/fate/ffprobe_default +++ b/tests/ref/fate/ffprobe_default @@ -8,7 +8,7 @@ dts_time=0.000000 duration=1024 duration_time=0.023220 size=2048 -pos=647 +pos=669 flags=K_ [/PACKET] [FRAME] @@ -23,7 +23,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=647 +pkt_pos=669 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -40,7 +40,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=230400 -pos=2722 +pos=2744 flags=K_ [/PACKET] [FRAME] @@ -55,7 +55,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=2722 +pkt_pos=2744 pkt_size=230400 width=320 height=240 @@ -83,7 +83,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=30000 -pos=233143 +pos=233165 flags=K_ [/PACKET] [FRAME] @@ -98,7 +98,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=233143 +pkt_pos=233165 pkt_size=30000 width=100 height=100 @@ -126,7 +126,7 @@ dts_time=0.023220 duration=1024 duration_time=0.023220 size=2048 -pos=263148 +pos=263170 flags=K_ [/PACKET] [FRAME] @@ -141,7 +141,7 @@ best_effort_timestamp=1024 best_effort_timestamp_time=0.023220 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=263148 +pkt_pos=263170 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -158,7 +158,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=230400 -pos=265226 +pos=265248 flags=K_ [/PACKET] [FRAME] @@ -173,7 +173,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=265226 +pkt_pos=265248 pkt_size=230400 width=320 height=240 @@ -201,7 +201,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=30000 -pos=495650 +pos=495672 flags=K_ [/PACKET] [FRAME] @@ -216,7 +216,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=495650 +pkt_pos=495672 pkt_size=30000 width=100 height=100 @@ -244,7 +244,7 @@ dts_time=0.046440 duration=1024 duration_time=0.023220 size=2048 -pos=525655 +pos=525677 flags=K_ [/PACKET] [FRAME] @@ -259,7 +259,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.046440 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=525655 +pkt_pos=525677 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -276,7 +276,7 @@ dts_time=0.069660 duration=1024 duration_time=0.023220 size=2048 -pos=527726 +pos=527748 flags=K_ [/PACKET] [FRAME] @@ -291,7 +291,7 @@ best_effort_timestamp=3072 best_effort_timestamp_time=0.069660 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=527726 +pkt_pos=527748 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -308,7 +308,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=230400 -pos=529804 +pos=529826 flags=K_ [/PACKET] [FRAME] @@ -323,7 +323,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=529804 +pkt_pos=529826 pkt_size=230400 width=320 height=240 @@ -351,7 +351,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=30000 -pos=760228 +pos=760250 flags=K_ [/PACKET] [FRAME] @@ -366,7 +366,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=760228 +pkt_pos=760250 pkt_size=30000 width=100 height=100 @@ -394,7 +394,7 @@ dts_time=0.092880 duration=1024 duration_time=0.023220 size=2048 -pos=790233 +pos=790255 flags=K_ [/PACKET] [FRAME] @@ -409,7 +409,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.092880 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=790233 +pkt_pos=790255 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -426,7 +426,7 @@ dts_time=0.116100 duration=393 duration_time=0.008912 size=786 -pos=792304 +pos=792326 flags=K_ [/PACKET] [FRAME] @@ -441,7 +441,7 @@ best_effort_timestamp=5120 best_effort_timestamp_time=0.116100 pkt_duration=393 pkt_duration_time=0.008912 -pkt_pos=792304 +pkt_pos=792326 pkt_size=786 sample_fmt=s16 nb_samples=393 @@ -458,7 +458,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=230400 -pos=793120 +pos=793142 flags=K_ [/PACKET] [FRAME] @@ -473,7 +473,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=793120 +pkt_pos=793142 pkt_size=230400 width=320 height=240 @@ -501,7 +501,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=30000 -pos=1023544 +pos=1023566 flags=K_ [/PACKET] [FRAME] @@ -516,7 +516,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=1023544 +pkt_pos=1023566 pkt_size=30000 width=100 height=100 @@ -619,7 +619,7 @@ bits_per_raw_sample=N/A nb_frames=N/A nb_read_frames=4 nb_read_packets=4 -DISPOSITION:default=0 +DISPOSITION:default=1 DISPOSITION:dub=0 DISPOSITION:original=0 DISPOSITION:comment=0 @@ -705,8 +705,8 @@ nb_programs=0 format_name=nut start_time=0.000000 duration=0.120000 -size=1053624 -bit_rate=70241600 +size=1053646 +bit_rate=70243066 probe_score=100 TAG:title=ffprobe test file TAG:comment='A comment with CSV, XML & JSON special chars': diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat index 4b0b4b3881..e77dec6b84 100644 --- a/tests/ref/fate/ffprobe_flat +++ b/tests/ref/fate/ffprobe_flat @@ -7,7 +7,7 @@ packets_and_frames.packet.0.dts_time="0.000000" packets_and_frames.packet.0.duration=1024 packets_and_frames.packet.0.duration_time="0.023220" packets_and_frames.packet.0.size="2048" -packets_and_frames.packet.0.pos="647" +packets_and_frames.packet.0.pos="669" packets_and_frames.packet.0.flags="K_" packets_and_frames.frame.0.media_type="audio" packets_and_frames.frame.0.stream_index=0 @@ -20,7 +20,7 @@ packets_and_frames.frame.0.best_effort_timestamp=0 packets_and_frames.frame.0.best_effort_timestamp_time="0.000000" packets_and_frames.frame.0.pkt_duration=1024 packets_and_frames.frame.0.pkt_duration_time="0.023220" -packets_and_frames.frame.0.pkt_pos="647" +packets_and_frames.frame.0.pkt_pos="669" packets_and_frames.frame.0.pkt_size="2048" packets_and_frames.frame.0.sample_fmt="s16" packets_and_frames.frame.0.nb_samples=1024 @@ -35,7 +35,7 @@ packets_and_frames.packet.1.dts_time="0.000000" packets_and_frames.packet.1.duration=2048 packets_and_frames.packet.1.duration_time="0.040000" packets_and_frames.packet.1.size="230400" -packets_and_frames.packet.1.pos="2722" +packets_and_frames.packet.1.pos="2744" packets_and_frames.packet.1.flags="K_" packets_and_frames.frame.1.media_type="video" packets_and_frames.frame.1.stream_index=1 @@ -48,7 +48,7 @@ packets_and_frames.frame.1.best_effort_timestamp=0 packets_and_frames.frame.1.best_effort_timestamp_time="0.000000" packets_and_frames.frame.1.pkt_duration=2048 packets_and_frames.frame.1.pkt_duration_time="0.040000" -packets_and_frames.frame.1.pkt_pos="2722" +packets_and_frames.frame.1.pkt_pos="2744" packets_and_frames.frame.1.pkt_size="230400" packets_and_frames.frame.1.width=320 packets_and_frames.frame.1.height=240 @@ -74,7 +74,7 @@ packets_and_frames.packet.2.dts_time="0.000000" packets_and_frames.packet.2.duration=2048 packets_and_frames.packet.2.duration_time="0.040000" packets_and_frames.packet.2.size="30000" -packets_and_frames.packet.2.pos="233143" +packets_and_frames.packet.2.pos="233165" packets_and_frames.packet.2.flags="K_" packets_and_frames.frame.2.media_type="video" packets_and_frames.frame.2.stream_index=2 @@ -87,7 +87,7 @@ packets_and_frames.frame.2.best_effort_timestamp=0 packets_and_frames.frame.2.best_effort_timestamp_time="0.000000" packets_and_frames.frame.2.pkt_duration=2048 packets_and_frames.frame.2.pkt_duration_time="0.040000" -packets_and_frames.frame.2.pkt_pos="233143" +packets_and_frames.frame.2.pkt_pos="233165" packets_and_frames.frame.2.pkt_size="30000" packets_and_frames.frame.2.width=100 packets_and_frames.frame.2.height=100 @@ -113,7 +113,7 @@ packets_and_frames.packet.3.dts_time="0.023220" packets_and_frames.packet.3.duration=1024 packets_and_frames.packet.3.duration_time="0.023220" packets_and_frames.packet.3.size="2048" -packets_and_frames.packet.3.pos="263148" +packets_and_frames.packet.3.pos="263170" packets_and_frames.packet.3.flags="K_" packets_and_frames.frame.3.media_type="audio" packets_and_frames.frame.3.stream_index=0 @@ -126,7 +126,7 @@ packets_and_frames.frame.3.best_effort_timestamp=1024 packets_and_frames.frame.3.best_effort_timestamp_time="0.023220" packets_and_frames.frame.3.pkt_duration=1024 packets_and_frames.frame.3.pkt_duration_time="0.023220" -packets_and_frames.frame.3.pkt_pos="263148" +packets_and_frames.frame.3.pkt_pos="263170" packets_and_frames.frame.3.pkt_size="2048" packets_and_frames.frame.3.sample_fmt="s16" packets_and_frames.frame.3.nb_samples=1024 @@ -141,7 +141,7 @@ packets_and_frames.packet.4.dts_time="0.040000" packets_and_frames.packet.4.duration=2048 packets_and_frames.packet.4.duration_time="0.040000" packets_and_frames.packet.4.size="230400" -packets_and_frames.packet.4.pos="265226" +packets_and_frames.packet.4.pos="265248" packets_and_frames.packet.4.flags="K_" packets_and_frames.frame.4.media_type="video" packets_and_frames.frame.4.stream_index=1 @@ -154,7 +154,7 @@ packets_and_frames.frame.4.best_effort_timestamp=2048 packets_and_frames.frame.4.best_effort_timestamp_time="0.040000" packets_and_frames.frame.4.pkt_duration=2048 packets_and_frames.frame.4.pkt_duration_time="0.040000" -packets_and_frames.frame.4.pkt_pos="265226" +packets_and_frames.frame.4.pkt_pos="265248" packets_and_frames.frame.4.pkt_size="230400" packets_and_frames.frame.4.width=320 packets_and_frames.frame.4.height=240 @@ -180,7 +180,7 @@ packets_and_frames.packet.5.dts_time="0.040000" packets_and_frames.packet.5.duration=2048 packets_and_frames.packet.5.duration_time="0.040000" packets_and_frames.packet.5.size="30000" -packets_and_frames.packet.5.pos="495650" +packets_and_frames.packet.5.pos="495672" packets_and_frames.packet.5.flags="K_" packets_and_frames.frame.5.media_type="video" packets_and_frames.frame.5.stream_index=2 @@ -193,7 +193,7 @@ packets_and_frames.frame.5.best_effort_timestamp=2048 packets_and_frames.frame.5.best_effort_timestamp_time="0.040000" packets_and_frames.frame.5.pkt_duration=2048 packets_and_frames.frame.5.pkt_duration_time="0.040000" -packets_and_frames.frame.5.pkt_pos="495650" +packets_and_frames.frame.5.pkt_pos="495672" packets_and_frames.frame.5.pkt_size="30000" packets_and_frames.frame.5.width=100 packets_and_frames.frame.5.height=100 @@ -219,7 +219,7 @@ packets_and_frames.packet.6.dts_time="0.046440" packets_and_frames.packet.6.duration=1024 packets_and_frames.packet.6.duration_time="0.023220" packets_and_frames.packet.6.size="2048" -packets_and_frames.packet.6.pos="525655" +packets_and_frames.packet.6.pos="525677" packets_and_frames.packet.6.flags="K_" packets_and_frames.frame.6.media_type="audio" packets_and_frames.frame.6.stream_index=0 @@ -232,7 +232,7 @@ packets_and_frames.frame.6.best_effort_timestamp=2048 packets_and_frames.frame.6.best_effort_timestamp_time="0.046440" packets_and_frames.frame.6.pkt_duration=1024 packets_and_frames.frame.6.pkt_duration_time="0.023220" -packets_and_frames.frame.6.pkt_pos="525655" +packets_and_frames.frame.6.pkt_pos="525677" packets_and_frames.frame.6.pkt_size="2048" packets_and_frames.frame.6.sample_fmt="s16" packets_and_frames.frame.6.nb_samples=1024 @@ -247,7 +247,7 @@ packets_and_frames.packet.7.dts_time="0.069660" packets_and_frames.packet.7.duration=1024 packets_and_frames.packet.7.duration_time="0.023220" packets_and_frames.packet.7.size="2048" -packets_and_frames.packet.7.pos="527726" +packets_and_frames.packet.7.pos="527748" packets_and_frames.packet.7.flags="K_" packets_and_frames.frame.7.media_type="audio" packets_and_frames.frame.7.stream_index=0 @@ -260,7 +260,7 @@ packets_and_frames.frame.7.best_effort_timestamp=3072 packets_and_frames.frame.7.best_effort_timestamp_time="0.069660" packets_and_frames.frame.7.pkt_duration=1024 packets_and_frames.frame.7.pkt_duration_time="0.023220" -packets_and_frames.frame.7.pkt_pos="527726" +packets_and_frames.frame.7.pkt_pos="527748" packets_and_frames.frame.7.pkt_size="2048" packets_and_frames.frame.7.sample_fmt="s16" packets_and_frames.frame.7.nb_samples=1024 @@ -275,7 +275,7 @@ packets_and_frames.packet.8.dts_time="0.080000" packets_and_frames.packet.8.duration=2048 packets_and_frames.packet.8.duration_time="0.040000" packets_and_frames.packet.8.size="230400" -packets_and_frames.packet.8.pos="529804" +packets_and_frames.packet.8.pos="529826" packets_and_frames.packet.8.flags="K_" packets_and_frames.frame.8.media_type="video" packets_and_frames.frame.8.stream_index=1 @@ -288,7 +288,7 @@ packets_and_frames.frame.8.best_effort_timestamp=4096 packets_and_frames.frame.8.best_effort_timestamp_time="0.080000" packets_and_frames.frame.8.pkt_duration=2048 packets_and_frames.frame.8.pkt_duration_time="0.040000" -packets_and_frames.frame.8.pkt_pos="529804" +packets_and_frames.frame.8.pkt_pos="529826" packets_and_frames.frame.8.pkt_size="230400" packets_and_frames.frame.8.width=320 packets_and_frames.frame.8.height=240 @@ -314,7 +314,7 @@ packets_and_frames.packet.9.dts_time="0.080000" packets_and_frames.packet.9.duration=2048 packets_and_frames.packet.9.duration_time="0.040000" packets_and_frames.packet.9.size="30000" -packets_and_frames.packet.9.pos="760228" +packets_and_frames.packet.9.pos="760250" packets_and_frames.packet.9.flags="K_" packets_and_frames.frame.9.media_type="video" packets_and_frames.frame.9.stream_index=2 @@ -327,7 +327,7 @@ packets_and_frames.frame.9.best_effort_timestamp=4096 packets_and_frames.frame.9.best_effort_timestamp_time="0.080000" packets_and_frames.frame.9.pkt_duration=2048 packets_and_frames.frame.9.pkt_duration_time="0.040000" -packets_and_frames.frame.9.pkt_pos="760228" +packets_and_frames.frame.9.pkt_pos="760250" packets_and_frames.frame.9.pkt_size="30000" packets_and_frames.frame.9.width=100 packets_and_frames.frame.9.height=100 @@ -353,7 +353,7 @@ packets_and_frames.packet.10.dts_time="0.092880" packets_and_frames.packet.10.duration=1024 packets_and_frames.packet.10.duration_time="0.023220" packets_and_frames.packet.10.size="2048" -packets_and_frames.packet.10.pos="790233" +packets_and_frames.packet.10.pos="790255" packets_and_frames.packet.10.flags="K_" packets_and_frames.frame.10.media_type="audio" packets_and_frames.frame.10.stream_index=0 @@ -366,7 +366,7 @@ packets_and_frames.frame.10.best_effort_timestamp=4096 packets_and_frames.frame.10.best_effort_timestamp_time="0.092880" packets_and_frames.frame.10.pkt_duration=1024 packets_and_frames.frame.10.pkt_duration_time="0.023220" -packets_and_frames.frame.10.pkt_pos="790233" +packets_and_frames.frame.10.pkt_pos="790255" packets_and_frames.frame.10.pkt_size="2048" packets_and_frames.frame.10.sample_fmt="s16" packets_and_frames.frame.10.nb_samples=1024 @@ -381,7 +381,7 @@ packets_and_frames.packet.11.dts_time="0.116100" packets_and_frames.packet.11.duration=393 packets_and_frames.packet.11.duration_time="0.008912" packets_and_frames.packet.11.size="786" -packets_and_frames.packet.11.pos="792304" +packets_and_frames.packet.11.pos="792326" packets_and_frames.packet.11.flags="K_" packets_and_frames.frame.11.media_type="audio" packets_and_frames.frame.11.stream_index=0 @@ -394,7 +394,7 @@ packets_and_frames.frame.11.best_effort_timestamp=5120 packets_and_frames.frame.11.best_effort_timestamp_time="0.116100" packets_and_frames.frame.11.pkt_duration=393 packets_and_frames.frame.11.pkt_duration_time="0.008912" -packets_and_frames.frame.11.pkt_pos="792304" +packets_and_frames.frame.11.pkt_pos="792326" packets_and_frames.frame.11.pkt_size="786" packets_and_frames.frame.11.sample_fmt="s16" packets_and_frames.frame.11.nb_samples=393 @@ -409,7 +409,7 @@ packets_and_frames.packet.12.dts_time="0.120000" packets_and_frames.packet.12.duration=2048 packets_and_frames.packet.12.duration_time="0.040000" packets_and_frames.packet.12.size="230400" -packets_and_frames.packet.12.pos="793120" +packets_and_frames.packet.12.pos="793142" packets_and_frames.packet.12.flags="K_" packets_and_frames.frame.12.media_type="video" packets_and_frames.frame.12.stream_index=1 @@ -422,7 +422,7 @@ packets_and_frames.frame.12.best_effort_timestamp=6144 packets_and_frames.frame.12.best_effort_timestamp_time="0.120000" packets_and_frames.frame.12.pkt_duration=2048 packets_and_frames.frame.12.pkt_duration_time="0.040000" -packets_and_frames.frame.12.pkt_pos="793120" +packets_and_frames.frame.12.pkt_pos="793142" packets_and_frames.frame.12.pkt_size="230400" packets_and_frames.frame.12.width=320 packets_and_frames.frame.12.height=240 @@ -448,7 +448,7 @@ packets_and_frames.packet.13.dts_time="0.120000" packets_and_frames.packet.13.duration=2048 packets_and_frames.packet.13.duration_time="0.040000" packets_and_frames.packet.13.size="30000" -packets_and_frames.packet.13.pos="1023544" +packets_and_frames.packet.13.pos="1023566" packets_and_frames.packet.13.flags="K_" packets_and_frames.frame.13.media_type="video" packets_and_frames.frame.13.stream_index=2 @@ -461,7 +461,7 @@ packets_and_frames.frame.13.best_effort_timestamp=6144 packets_and_frames.frame.13.best_effort_timestamp_time="0.120000" packets_and_frames.frame.13.pkt_duration=2048 packets_and_frames.frame.13.pkt_duration_time="0.040000" -packets_and_frames.frame.13.pkt_pos="1023544" +packets_and_frames.frame.13.pkt_pos="1023566" packets_and_frames.frame.13.pkt_size="30000" packets_and_frames.frame.13.width=100 packets_and_frames.frame.13.height=100 @@ -560,7 +560,7 @@ streams.stream.1.bits_per_raw_sample="N/A" streams.stream.1.nb_frames="N/A" streams.stream.1.nb_read_frames="4" streams.stream.1.nb_read_packets="4" -streams.stream.1.disposition.default=0 +streams.stream.1.disposition.default=1 streams.stream.1.disposition.dub=0 streams.stream.1.disposition.original=0 streams.stream.1.disposition.comment=0 @@ -642,8 +642,8 @@ format.nb_programs=0 format.format_name="nut" format.start_time="0.000000" format.duration="0.120000" -format.size="1053624" -format.bit_rate="70241600" +format.size="1053646" +format.bit_rate="70243066" format.probe_score=100 format.tags.title="ffprobe test file" format.tags.comment="'A comment with CSV, XML & JSON special chars': " diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini index f64c4e891d..cff7d96003 100644 --- a/tests/ref/fate/ffprobe_ini +++ b/tests/ref/fate/ffprobe_ini @@ -10,7 +10,7 @@ dts_time=0.000000 duration=1024 duration_time=0.023220 size=2048 -pos=647 +pos=669 flags=K_ [packets_and_frames.frame.0] @@ -25,7 +25,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=647 +pkt_pos=669 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -42,7 +42,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=230400 -pos=2722 +pos=2744 flags=K_ [packets_and_frames.frame.1] @@ -57,7 +57,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=2722 +pkt_pos=2744 pkt_size=230400 width=320 height=240 @@ -85,7 +85,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=30000 -pos=233143 +pos=233165 flags=K_ [packets_and_frames.frame.2] @@ -100,7 +100,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=233143 +pkt_pos=233165 pkt_size=30000 width=100 height=100 @@ -128,7 +128,7 @@ dts_time=0.023220 duration=1024 duration_time=0.023220 size=2048 -pos=263148 +pos=263170 flags=K_ [packets_and_frames.frame.3] @@ -143,7 +143,7 @@ best_effort_timestamp=1024 best_effort_timestamp_time=0.023220 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=263148 +pkt_pos=263170 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -160,7 +160,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=230400 -pos=265226 +pos=265248 flags=K_ [packets_and_frames.frame.4] @@ -175,7 +175,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=265226 +pkt_pos=265248 pkt_size=230400 width=320 height=240 @@ -203,7 +203,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=30000 -pos=495650 +pos=495672 flags=K_ [packets_and_frames.frame.5] @@ -218,7 +218,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=495650 +pkt_pos=495672 pkt_size=30000 width=100 height=100 @@ -246,7 +246,7 @@ dts_time=0.046440 duration=1024 duration_time=0.023220 size=2048 -pos=525655 +pos=525677 flags=K_ [packets_and_frames.frame.6] @@ -261,7 +261,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.046440 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=525655 +pkt_pos=525677 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -278,7 +278,7 @@ dts_time=0.069660 duration=1024 duration_time=0.023220 size=2048 -pos=527726 +pos=527748 flags=K_ [packets_and_frames.frame.7] @@ -293,7 +293,7 @@ best_effort_timestamp=3072 best_effort_timestamp_time=0.069660 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=527726 +pkt_pos=527748 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -310,7 +310,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=230400 -pos=529804 +pos=529826 flags=K_ [packets_and_frames.frame.8] @@ -325,7 +325,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=529804 +pkt_pos=529826 pkt_size=230400 width=320 height=240 @@ -353,7 +353,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=30000 -pos=760228 +pos=760250 flags=K_ [packets_and_frames.frame.9] @@ -368,7 +368,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=760228 +pkt_pos=760250 pkt_size=30000 width=100 height=100 @@ -396,7 +396,7 @@ dts_time=0.092880 duration=1024 duration_time=0.023220 size=2048 -pos=790233 +pos=790255 flags=K_ [packets_and_frames.frame.10] @@ -411,7 +411,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.092880 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=790233 +pkt_pos=790255 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -428,7 +428,7 @@ dts_time=0.116100 duration=393 duration_time=0.008912 size=786 -pos=792304 +pos=792326 flags=K_ [packets_and_frames.frame.11] @@ -443,7 +443,7 @@ best_effort_timestamp=5120 best_effort_timestamp_time=0.116100 pkt_duration=393 pkt_duration_time=0.008912 -pkt_pos=792304 +pkt_pos=792326 pkt_size=786 sample_fmt=s16 nb_samples=393 @@ -460,7 +460,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=230400 -pos=793120 +pos=793142 flags=K_ [packets_and_frames.frame.12] @@ -475,7 +475,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=793120 +pkt_pos=793142 pkt_size=230400 width=320 height=240 @@ -503,7 +503,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=30000 -pos=1023544 +pos=1023566 flags=K_ [packets_and_frames.frame.13] @@ -518,7 +518,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=1023544 +pkt_pos=1023566 pkt_size=30000 width=100 height=100 @@ -627,7 +627,7 @@ nb_read_frames=4 nb_read_packets=4 [streams.stream.1.disposition] -default=0 +default=1 dub=0 original=0 comment=0 @@ -719,8 +719,8 @@ nb_programs=0 format_name=nut start_time=0.000000 duration=0.120000 -size=1053624 -bit_rate=70241600 +size=1053646 +bit_rate=70243066 probe_score=100 [format.tags] diff --git a/tests/ref/fate/ffprobe_json b/tests/ref/fate/ffprobe_json index a94776030b..9816700b53 100644 --- a/tests/ref/fate/ffprobe_json +++ b/tests/ref/fate/ffprobe_json @@ -11,7 +11,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "647", + "pos": "669", "flags": "K_" }, { @@ -27,7 +27,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "647", + "pkt_pos": "669", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -44,7 +44,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "2722", + "pos": "2744", "flags": "K_" }, { @@ -60,7 +60,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "2722", + "pkt_pos": "2744", "pkt_size": "230400", "width": 320, "height": 240, @@ -84,7 +84,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "233143", + "pos": "233165", "flags": "K_" }, { @@ -100,7 +100,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "233143", + "pkt_pos": "233165", "pkt_size": "30000", "width": 100, "height": 100, @@ -124,7 +124,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "263148", + "pos": "263170", "flags": "K_" }, { @@ -140,7 +140,7 @@ "best_effort_timestamp_time": "0.023220", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "263148", + "pkt_pos": "263170", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -157,7 +157,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "265226", + "pos": "265248", "flags": "K_" }, { @@ -173,7 +173,7 @@ "best_effort_timestamp_time": "0.040000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "265226", + "pkt_pos": "265248", "pkt_size": "230400", "width": 320, "height": 240, @@ -197,7 +197,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "495650", + "pos": "495672", "flags": "K_" }, { @@ -213,7 +213,7 @@ "best_effort_timestamp_time": "0.040000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "495650", + "pkt_pos": "495672", "pkt_size": "30000", "width": 100, "height": 100, @@ -237,7 +237,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "525655", + "pos": "525677", "flags": "K_" }, { @@ -253,7 +253,7 @@ "best_effort_timestamp_time": "0.046440", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "525655", + "pkt_pos": "525677", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -270,7 +270,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "527726", + "pos": "527748", "flags": "K_" }, { @@ -286,7 +286,7 @@ "best_effort_timestamp_time": "0.069660", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "527726", + "pkt_pos": "527748", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -303,7 +303,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "529804", + "pos": "529826", "flags": "K_" }, { @@ -319,7 +319,7 @@ "best_effort_timestamp_time": "0.080000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "529804", + "pkt_pos": "529826", "pkt_size": "230400", "width": 320, "height": 240, @@ -343,7 +343,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "760228", + "pos": "760250", "flags": "K_" }, { @@ -359,7 +359,7 @@ "best_effort_timestamp_time": "0.080000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "760228", + "pkt_pos": "760250", "pkt_size": "30000", "width": 100, "height": 100, @@ -383,7 +383,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "790233", + "pos": "790255", "flags": "K_" }, { @@ -399,7 +399,7 @@ "best_effort_timestamp_time": "0.092880", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "790233", + "pkt_pos": "790255", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -416,7 +416,7 @@ "duration": 393, "duration_time": "0.008912", "size": "786", - "pos": "792304", + "pos": "792326", "flags": "K_" }, { @@ -432,7 +432,7 @@ "best_effort_timestamp_time": "0.116100", "pkt_duration": 393, "pkt_duration_time": "0.008912", - "pkt_pos": "792304", + "pkt_pos": "792326", "pkt_size": "786", "sample_fmt": "s16", "nb_samples": 393, @@ -449,7 +449,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "793120", + "pos": "793142", "flags": "K_" }, { @@ -465,7 +465,7 @@ "best_effort_timestamp_time": "0.120000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "793120", + "pkt_pos": "793142", "pkt_size": "230400", "width": 320, "height": 240, @@ -489,7 +489,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "1023544", + "pos": "1023566", "flags": "K_" }, { @@ -505,7 +505,7 @@ "best_effort_timestamp_time": "0.120000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "1023544", + "pkt_pos": "1023566", "pkt_size": "30000", "width": 100, "height": 100, @@ -588,7 +588,7 @@ "nb_read_frames": "4", "nb_read_packets": "4", "disposition": { - "default": 0, + "default": 1, "dub": 0, "original": 0, "comment": 0, @@ -668,8 +668,8 @@ "format_name": "nut", "start_time": "0.000000", "duration": "0.120000", - "size": "1053624", - "bit_rate": "70241600", + "size": "1053646", + "bit_rate": "70243066", "probe_score": 100, "tags": { "title": "ffprobe test file", diff --git a/tests/ref/fate/ffprobe_xml b/tests/ref/fate/ffprobe_xml index 88623f0e11..4f702bc984 100644 --- a/tests/ref/fate/ffprobe_xml +++ b/tests/ref/fate/ffprobe_xml @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38,7 +38,7 @@ - + @@ -49,7 +49,7 @@ - + diff --git a/tests/ref/fate/ffprobe_xsd b/tests/ref/fate/ffprobe_xsd index c4a6bf86d2..62d011ad9c 100644 --- a/tests/ref/fate/ffprobe_xsd +++ b/tests/ref/fate/ffprobe_xsd @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38,7 +38,7 @@ - + @@ -49,7 +49,7 @@ - + diff --git a/tests/ref/fate/matroska-mastering-display-metadata b/tests/ref/fate/matroska-mastering-display-metadata index 627a8c103e..8f5d7b6a22 100644 --- a/tests/ref/fate/matroska-mastering-display-metadata +++ b/tests/ref/fate/matroska-mastering-display-metadata @@ -1,5 +1,5 @@ -4f97d718f706e241df9f6c95ac1c721a *tests/data/fate/matroska-mastering-display-metadata.matroska -1669701 tests/data/fate/matroska-mastering-display-metadata.matroska +542ababe5c088ab925ee49373d8b8a85 *tests/data/fate/matroska-mastering-display-metadata.matroska +1669695 tests/data/fate/matroska-mastering-display-metadata.matroska #extradata 0: 4, 0x040901a3 #extradata 3: 200, 0x506463a8 #tb 0: 1/1000 From 20c66fe2f9ac69dbfa2f3cfc2386aae4ba7adc60 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 16 Nov 2021 11:19:10 +0100 Subject: [PATCH 174/894] lavfi/vulkan: fix issues the previous commit introduced One typo and one think-before-you-paste. --- libavfilter/vulkan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index 3bb4eea7a1..48f02e4603 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -119,7 +119,7 @@ void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, av_assert0(0); /* Should never happen */ } - if (qf->actual_queues) + if (!nb_queues) qf->nb_queues = qf->actual_queues; else qf->nb_queues = nb_queues; @@ -1258,10 +1258,10 @@ void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, /* If a set has never been updated, update all queues' sets. */ if (!pl->desc_set_initialized[set_id]) { for (int i = 0; i < pl->qf->nb_queues; i++) { - set_id = set_id*pl->qf->nb_queues + i; + int idx = set_id*pl->qf->nb_queues + i; vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, - pl->desc_set[set_id], - pl->desc_template[set_id], + pl->desc_set[idx], + pl->desc_template[idx], s); } pl->desc_set_initialized[set_id] = 1; From 6f04cf54f532ad5695072303d74cddaa591f9aa1 Mon Sep 17 00:00:00 2001 From: Jonathan Wright Date: Mon, 28 Sep 2020 13:35:51 +0100 Subject: [PATCH 175/894] aarch64: Use ret x instead of br x where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change AArch64 assembly code to use: ret x instead of: br x "ret x" is already used in a lot of places so this patch makes it consistent across the code base. This does not change behavior or performance. In addition, this change reduces the number of landing pads needed in a subsequent patch to support the Armv8.5-A Branch Target Identification (BTI) security feature. Signed-off-by: Jonathan Wright Signed-off-by: Martin Storsjö --- libavcodec/aarch64/simple_idct_neon.S | 2 +- libavcodec/aarch64/vp9itxfm_16bpp_neon.S | 28 ++++++------- libavcodec/aarch64/vp9itxfm_neon.S | 26 ++++++------ libavcodec/aarch64/vp9lpf_16bpp_neon.S | 38 ++++++++--------- libavcodec/aarch64/vp9lpf_neon.S | 52 ++++++++++++------------ 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/libavcodec/aarch64/simple_idct_neon.S b/libavcodec/aarch64/simple_idct_neon.S index 5e4d021a97..210182ff21 100644 --- a/libavcodec/aarch64/simple_idct_neon.S +++ b/libavcodec/aarch64/simple_idct_neon.S @@ -58,7 +58,7 @@ endconst .endm .macro idct_end - br x10 + ret x10 .endm .macro smull1 a, b, c diff --git a/libavcodec/aarch64/vp9itxfm_16bpp_neon.S b/libavcodec/aarch64/vp9itxfm_16bpp_neon.S index 68296d9c40..c5f43d36a3 100644 --- a/libavcodec/aarch64/vp9itxfm_16bpp_neon.S +++ b/libavcodec/aarch64/vp9itxfm_16bpp_neon.S @@ -1040,7 +1040,7 @@ function \txfm\()16_1d_4x16_pass1_neon .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 store \i, x0, #16 .endr - br x14 + ret x14 1: // Special case: For the last input column (x1 == 12), // which would be stored as the last row in the temp buffer, @@ -1068,7 +1068,7 @@ function \txfm\()16_1d_4x16_pass1_neon mov v29.16b, v17.16b mov v30.16b, v18.16b mov v31.16b, v19.16b - br x14 + ret x14 endfunc // Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it, @@ -1098,7 +1098,7 @@ function \txfm\()16_1d_4x16_pass2_neon load_add_store v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s load_add_store v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s - br x14 + ret x14 endfunc .endm @@ -1208,7 +1208,7 @@ function vp9_\txfm1\()_\txfm2\()_16x16_add_16_neon ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 .endif - br x15 + ret x15 endfunc function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_10_neon, export=1 @@ -1264,7 +1264,7 @@ function idct16_1d_4x16_pass1_quarter_neon st1 {v23.4s}, [x0], #16 st1 {v27.4s}, [x0], #16 st1 {v31.4s}, [x0], #16 - br x14 + ret x14 endfunc function idct16_1d_4x16_pass2_quarter_neon @@ -1286,7 +1286,7 @@ function idct16_1d_4x16_pass2_quarter_neon load_add_store v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s load_add_store v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s - br x14 + ret x14 endfunc function idct16_1d_4x16_pass1_half_neon @@ -1313,7 +1313,7 @@ function idct16_1d_4x16_pass1_half_neon .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 store \i, x0, #16 .endr - br x14 + ret x14 1: // Special case: For the second input column (r1 == 4), // which would be stored as the second row in the temp buffer, @@ -1341,7 +1341,7 @@ function idct16_1d_4x16_pass1_half_neon mov v21.16b, v17.16b mov v22.16b, v18.16b mov v23.16b, v19.16b - br x14 + ret x14 endfunc function idct16_1d_4x16_pass2_half_neon @@ -1364,7 +1364,7 @@ function idct16_1d_4x16_pass2_half_neon load_add_store v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s load_add_store v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s - br x14 + ret x14 endfunc .macro idct16_partial size @@ -1390,7 +1390,7 @@ function idct16x16_\size\()_add_16_neon add sp, sp, #1024 ldp d8, d9, [sp], 0x10 - br x15 + ret x15 endfunc .endm @@ -1729,7 +1729,7 @@ function idct32_1d_4x32_pass1\suffix\()_neon store_rev v29.4s, v25.4s, v21.4s, v17.4s, v29.16b, v25.16b store_rev v28.4s, v24.4s, v20.4s, v16.4s, v28.16b, v24.16b .purgem store_rev - br x14 + ret x14 endfunc // This is mostly the same as 4x32_pass1, but without the transpose, @@ -1849,7 +1849,7 @@ function idct32_1d_4x32_pass2\suffix\()_neon load_acc_store v24.4s, v25.4s, v26.4s, v27.4s, 1 load_acc_store v28.4s, v29.4s, v30.4s, v31.4s, 1 .purgem load_acc_store - br x14 + ret x14 endfunc .endm @@ -1943,7 +1943,7 @@ function vp9_idct_idct_32x32_add_16_neon ldp d10, d11, [sp], 0x10 ldp d8, d9, [sp], 0x10 - br x15 + ret x15 endfunc function ff_vp9_idct_idct_32x32_add_10_neon, export=1 @@ -2009,7 +2009,7 @@ function idct32x32_\size\()_add_16_neon ldp d10, d11, [sp], 0x10 ldp d8, d9, [sp], 0x10 - br x15 + ret x15 endfunc .endm diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S index 99413b0f70..03272eae82 100644 --- a/libavcodec/aarch64/vp9itxfm_neon.S +++ b/libavcodec/aarch64/vp9itxfm_neon.S @@ -787,7 +787,7 @@ function \txfm\()16_1d_8x16_pass1_neon .irp i, 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31 store \i, x0, #16 .endr - br x14 + ret x14 1: // Special case: For the last input column (x1 == 8), // which would be stored as the last row in the temp buffer, @@ -806,7 +806,7 @@ function \txfm\()16_1d_8x16_pass1_neon mov v29.16b, v21.16b mov v30.16b, v22.16b mov v31.16b, v23.16b - br x14 + ret x14 endfunc // Read a vertical 8x16 slice out of a 16x16 matrix, do a transform on it, @@ -834,7 +834,7 @@ function \txfm\()16_1d_8x16_pass2_neon load_add_store v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b load_add_store v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b - br x14 + ret x14 endfunc .endm @@ -925,7 +925,7 @@ function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 .endif - br x15 + ret x15 endfunc .endm @@ -960,7 +960,7 @@ function idct16_1d_8x16_pass1_quarter_neon .irp i, 24, 25, 26, 27 store \i, x0, x9 .endr - br x14 + ret x14 endfunc function idct16_1d_8x16_pass2_quarter_neon @@ -978,7 +978,7 @@ function idct16_1d_8x16_pass2_quarter_neon load_add_store v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b load_add_store v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b - br x14 + ret x14 endfunc function idct16_1d_8x16_pass1_half_neon @@ -1003,7 +1003,7 @@ function idct16_1d_8x16_pass1_half_neon .irp i, 24, 25, 26, 27, 28, 29, 30, 31 store \i, x0, x9 .endr - br x14 + ret x14 endfunc function idct16_1d_8x16_pass2_half_neon @@ -1021,7 +1021,7 @@ function idct16_1d_8x16_pass2_half_neon load_add_store v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b load_add_store v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b - br x14 + ret x14 endfunc .macro idct16_partial size @@ -1038,7 +1038,7 @@ function idct16x16_\size\()_add_neon .endr add sp, sp, #512 - br x15 + ret x15 endfunc .endm @@ -1349,7 +1349,7 @@ function idct32_1d_8x32_pass1\suffix\()_neon store_rev v25.8h, v17.8h store_rev v24.8h, v16.8h .purgem store_rev - br x14 + ret x14 endfunc // This is mostly the same as 8x32_pass1, but without the transpose, @@ -1466,7 +1466,7 @@ function idct32_1d_8x32_pass2\suffix\()_neon load_acc_store v24.8h, v25.8h, v26.8h, v27.8h, 1 load_acc_store v28.8h, v29.8h, v30.8h, v31.8h, 1 .purgem load_acc_store - br x14 + ret x14 endfunc .endm @@ -1547,7 +1547,7 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1 ldp d8, d9, [sp], 0x10 ldp d10, d11, [sp], 0x10 - br x15 + ret x15 endfunc .macro idct32_partial size @@ -1572,7 +1572,7 @@ function idct32x32_\size\()_add_neon ldp d8, d9, [sp], 0x10 ldp d10, d11, [sp], 0x10 - br x15 + ret x15 endfunc .endm diff --git a/libavcodec/aarch64/vp9lpf_16bpp_neon.S b/libavcodec/aarch64/vp9lpf_16bpp_neon.S index 9869614a29..a092617b92 100644 --- a/libavcodec/aarch64/vp9lpf_16bpp_neon.S +++ b/libavcodec/aarch64/vp9lpf_16bpp_neon.S @@ -57,7 +57,7 @@ mov x12, v4.d[1] adds x11, x11, x12 b.ne 1f - br x10 + ret x10 1: .if \wd >= 8 @@ -193,7 +193,7 @@ b.eq 6f .else b.ne 1f - br x13 + ret x13 1: .endif @@ -252,7 +252,7 @@ b.ne 1f // If no pixels needed flat8in nor flat8out, jump to a // writeout of the inner 4 pixels - br x14 + ret x14 1: mov x11, v7.d[0] @@ -260,7 +260,7 @@ adds x11, x11, x12 b.ne 1f // If no pixels need flat8out, jump to a writeout of the inner 6 pixels - br x15 + ret x15 1: // flat8out @@ -434,7 +434,7 @@ function ff_\func\()_\bpp\()_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x16 + ret x16 .else b \func\()_16_neon .endif @@ -474,7 +474,7 @@ function ff_\func\()_\suffix\()_\bpp\()_neon, export=1 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 .endif - br x16 + ret x16 endfunc .endm @@ -508,7 +508,7 @@ function ff_vp9_loop_filter_\dir\()_\wd1\()\wd2\()_16_\bpp\()_neon, export=1 lsl w3, w14, #\bpp - 8 lsl w4, w15, #\bpp - 8 bl vp9_loop_filter_\dir\()_\wd2\()_8_16_neon - br x16 + ret x16 endfunc .endm @@ -541,7 +541,7 @@ function vp9_loop_filter_v_4_8_16_neon st1 {v25.8h}, [x0], x1 sub x0, x0, x1, lsl #1 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_v_4_8 @@ -589,7 +589,7 @@ function vp9_loop_filter_h_4_8_16_neon sub x0, x0, x1, lsl #3 add x0, x0, #4 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_h_4_8 @@ -620,7 +620,7 @@ function vp9_loop_filter_v_8_8_16_neon sub x0, x0, x1, lsl #1 sub x0, x0, x1 - br x10 + ret x10 6: sub x9, x0, x1, lsl #1 st1 {v22.8h}, [x9], x1 @@ -628,7 +628,7 @@ function vp9_loop_filter_v_8_8_16_neon st1 {v23.8h}, [x9], x1 st1 {v25.8h}, [x0], x1 sub x0, x0, x1, lsl #1 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_v_8_8 @@ -671,7 +671,7 @@ function vp9_loop_filter_h_8_8_16_neon sub x0, x0, x1, lsl #3 add x0, x0, #8 - br x10 + ret x10 6: // If we didn't need to do the flat8in part, we use the same writeback // as in loop_filter_h_4_8. @@ -688,7 +688,7 @@ function vp9_loop_filter_h_8_8_16_neon st1 {v25.d}[1], [x0], x1 sub x0, x0, x1, lsl #3 add x0, x0, #4 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_h_8_8 @@ -743,7 +743,7 @@ function vp9_loop_filter_v_16_8_16_neon sub x0, x0, x1, lsl #3 add x0, x0, x1 - br x10 + ret x10 8: add x9, x9, x1, lsl #2 // If we didn't do the flat8out part, the output is left in the @@ -756,7 +756,7 @@ function vp9_loop_filter_v_16_8_16_neon st1 {v26.8h}, [x0], x1 sub x0, x0, x1, lsl #1 sub x0, x0, x1 - br x10 + ret x10 7: sub x9, x0, x1, lsl #1 st1 {v22.8h}, [x9], x1 @@ -764,7 +764,7 @@ function vp9_loop_filter_v_16_8_16_neon st1 {v23.8h}, [x9], x1 st1 {v25.8h}, [x0], x1 sub x0, x0, x1, lsl #1 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_v_16_8, push=1 @@ -821,7 +821,7 @@ function vp9_loop_filter_h_16_8_16_neon st1 {v31.8h}, [x0], x1 sub x0, x0, x1, lsl #3 - br x10 + ret x10 8: // The same writeback as in loop_filter_h_8_8 sub x9, x0, #8 @@ -838,7 +838,7 @@ function vp9_loop_filter_h_16_8_16_neon st1 {v27.8h}, [x0], x1 sub x0, x0, x1, lsl #3 add x0, x0, #8 - br x10 + ret x10 7: // The same writeback as in loop_filter_h_4_8 sub x9, x0, #4 @@ -854,7 +854,7 @@ function vp9_loop_filter_h_16_8_16_neon st1 {v25.d}[1], [x0], x1 sub x0, x0, x1, lsl #3 add x0, x0, #4 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_h_16_8, push=1 diff --git a/libavcodec/aarch64/vp9lpf_neon.S b/libavcodec/aarch64/vp9lpf_neon.S index 0878763020..694ff8956f 100644 --- a/libavcodec/aarch64/vp9lpf_neon.S +++ b/libavcodec/aarch64/vp9lpf_neon.S @@ -399,7 +399,7 @@ .endif // If no pixels needed flat8in nor flat8out, jump to a // writeout of the inner 4 pixels - br x14 + ret x14 1: mov x5, v7.d[0] @@ -411,7 +411,7 @@ cbnz x5, 1f .endif // If no pixels need flat8out, jump to a writeout of the inner 6 pixels - br x15 + ret x15 1: // flat8out @@ -532,32 +532,32 @@ function vp9_loop_filter_4 loop_filter 4, .8b, 0, v16, v17, v18, v19, v28, v29, v30, v31 ret 9: - br x10 + ret x10 endfunc function vp9_loop_filter_4_16b_mix_44 loop_filter 4, .16b, 44, v16, v17, v18, v19, v28, v29, v30, v31 ret 9: - br x10 + ret x10 endfunc function vp9_loop_filter_8 loop_filter 8, .8b, 0, v16, v17, v18, v19, v28, v29, v30, v31 ret 6: - br x13 + ret x13 9: - br x10 + ret x10 endfunc function vp9_loop_filter_8_16b_mix loop_filter 8, .16b, 88, v16, v17, v18, v19, v28, v29, v30, v31 ret 6: - br x13 + ret x13 9: - br x10 + ret x10 endfunc function vp9_loop_filter_16 @@ -568,7 +568,7 @@ function vp9_loop_filter_16 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 endfunc function vp9_loop_filter_16_16b @@ -579,7 +579,7 @@ function vp9_loop_filter_16_16b ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 endfunc .macro loop_filter_4 @@ -648,7 +648,7 @@ function ff_vp9_loop_filter_v_4_8_neon, export=1 st1 {v23.8b}, [x9], x1 st1 {v25.8b}, [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_v_44_16_neon, export=1 @@ -672,7 +672,7 @@ function ff_vp9_loop_filter_v_44_16_neon, export=1 st1 {v23.16b}, [x9], x1 st1 {v25.16b}, [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_h_4_8_neon, export=1 @@ -714,7 +714,7 @@ function ff_vp9_loop_filter_h_4_8_neon, export=1 st1 {v25.s}[0], [x9], x1 st1 {v25.s}[1], [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_h_44_16_neon, export=1 @@ -766,7 +766,7 @@ function ff_vp9_loop_filter_h_44_16_neon, export=1 st1 {v25.s}[1], [x9], x1 st1 {v25.s}[3], [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_v_8_8_neon, export=1 @@ -793,14 +793,14 @@ function ff_vp9_loop_filter_v_8_8_neon, export=1 st1 {v23.8b}, [x9], x1 st1 {v26.8b}, [x0], x1 - br x10 + ret x10 6: sub x9, x0, x1, lsl #1 st1 {v22.8b}, [x9], x1 st1 {v24.8b}, [x0], x1 st1 {v23.8b}, [x9], x1 st1 {v25.8b}, [x0], x1 - br x10 + ret x10 endfunc .macro mix_v_16 mix @@ -828,14 +828,14 @@ function ff_vp9_loop_filter_v_\mix\()_16_neon, export=1 st1 {v23.16b}, [x9], x1 st1 {v26.16b}, [x0], x1 - br x10 + ret x10 6: sub x9, x0, x1, lsl #1 st1 {v22.16b}, [x9], x1 st1 {v24.16b}, [x0], x1 st1 {v23.16b}, [x9], x1 st1 {v25.16b}, [x0], x1 - br x10 + ret x10 endfunc .endm @@ -876,7 +876,7 @@ function ff_vp9_loop_filter_h_8_8_neon, export=1 st1 {v23.8b}, [x9], x1 st1 {v27.8b}, [x0], x1 - br x10 + ret x10 6: // If we didn't need to do the flat8in part, we use the same writeback // as in loop_filter_h_4_8. @@ -891,7 +891,7 @@ function ff_vp9_loop_filter_h_8_8_neon, export=1 st1 {v24.s}[1], [x0], x1 st1 {v25.s}[0], [x9], x1 st1 {v25.s}[1], [x0], x1 - br x10 + ret x10 endfunc .macro mix_h_16 mix @@ -942,7 +942,7 @@ function ff_vp9_loop_filter_h_\mix\()_16_neon, export=1 st1 {v27.8b}, [x9], x1 st1 {v27.d}[1], [x0], x1 - br x10 + ret x10 6: add x9, x9, #2 add x0, x0, #2 @@ -963,7 +963,7 @@ function ff_vp9_loop_filter_h_\mix\()_16_neon, export=1 st1 {v24.s}[3], [x0], x1 st1 {v25.s}[1], [x9], x1 st1 {v25.s}[3], [x0], x1 - br x10 + ret x10 endfunc .endm @@ -1022,7 +1022,7 @@ function ff_vp9_loop_filter_v_16_8_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: add x9, x9, x1, lsl #2 // If we didn't do the flat8out part, the output is left in the @@ -1091,7 +1091,7 @@ function ff_vp9_loop_filter_v_16_16_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: add x9, x9, x1, lsl #2 st1 {v21.16b}, [x9], x1 @@ -1168,7 +1168,7 @@ function ff_vp9_loop_filter_h_16_8_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: // The same writeback as in loop_filter_h_8_8 sub x9, x0, #4 @@ -1287,7 +1287,7 @@ function ff_vp9_loop_filter_h_16_16_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: sub x9, x0, #4 add x0, x9, x1, lsl #3 From 08b4716a9ed277afb4af69b07b751c9bd046aa70 Mon Sep 17 00:00:00 2001 From: Jonathan Wright Date: Mon, 28 Sep 2020 13:35:51 +0100 Subject: [PATCH 176/894] aarch64: Add Armv8.5-A BTI support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Branch Target Identifiers (BTIs) to all functions defined in AArch64 assembly files. Most of the BTI landing pads are added automatically by the 'function' macro. BTI support is turned on or off at compile time based on the presence of the __ARM_FEATURE_BTI_DEFAULT feature macro. A binary compiled with BTI support can be executed on an Armv8-A processor without BTI support because the instructions are defined in NOP space. Signed-off-by: Jonathan Wright Signed-off-by: Elijah Ahmad Signed-off-by: Martin Storsjö --- libavcodec/aarch64/fft_neon.S | 4 ++++ libavcodec/aarch64/h264idct_neon.S | 4 ++++ libavutil/aarch64/asm.S | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/libavcodec/aarch64/fft_neon.S b/libavcodec/aarch64/fft_neon.S index 862039f97d..b4020fc8c7 100644 --- a/libavcodec/aarch64/fft_neon.S +++ b/libavcodec/aarch64/fft_neon.S @@ -36,6 +36,7 @@ function fft4_neon + AARCH64_VALID_JUMP_TARGET ld1 {v0.2s,v1.2s,v2.2s,v3.2s}, [x0] fadd v4.2s, v0.2s, v1.2s // r0+r1,i0+i1 @@ -58,6 +59,7 @@ function fft4_neon endfunc function fft8_neon + AARCH64_VALID_JUMP_TARGET mov x1, x0 ld1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x0], #32 ld1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0] @@ -108,6 +110,7 @@ function fft8_neon endfunc function fft16_neon + AARCH64_VALID_JUMP_TARGET mov x1, x0 ld1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x0], #32 ld1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0], #32 @@ -337,6 +340,7 @@ endfunc .macro def_fft n, n2, n4 function fft\n\()_neon, align=6 + AARCH64_VALID_JUMP_TARGET sub sp, sp, #16 stp x28, x30, [sp] add x28, x0, #\n4*2*8 diff --git a/libavcodec/aarch64/h264idct_neon.S b/libavcodec/aarch64/h264idct_neon.S index 7de44205d3..7d2879b0ce 100644 --- a/libavcodec/aarch64/h264idct_neon.S +++ b/libavcodec/aarch64/h264idct_neon.S @@ -24,6 +24,7 @@ function ff_h264_idct_add_neon, export=1 .L_ff_h264_idct_add_neon: + AARCH64_VALID_CALL_TARGET ld1 {v0.4H, v1.4H, v2.4H, v3.4H}, [x1] sxtw x2, w2 movi v30.8H, #0 @@ -79,6 +80,7 @@ endfunc function ff_h264_idct_dc_add_neon, export=1 .L_ff_h264_idct_dc_add_neon: + AARCH64_VALID_CALL_TARGET sxtw x2, w2 mov w3, #0 ld1r {v2.8H}, [x1] @@ -266,6 +268,7 @@ endfunc function ff_h264_idct8_add_neon, export=1 .L_ff_h264_idct8_add_neon: + AARCH64_VALID_CALL_TARGET movi v19.8H, #0 sxtw x2, w2 ld1 {v24.8H, v25.8H}, [x1] @@ -330,6 +333,7 @@ endfunc function ff_h264_idct8_dc_add_neon, export=1 .L_ff_h264_idct8_dc_add_neon: + AARCH64_VALID_CALL_TARGET mov w3, #0 sxtw x2, w2 ld1r {v31.8H}, [x1] diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index d1fa72b3c6..bee91d59c3 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -36,6 +36,35 @@ # define __has_feature(x) 0 #endif +/* Support macros for the Armv8.5-A Branch Target Identification feature which + * requires emitting a .note.gnu.property section with the appropriate + * architecture-dependent feature bits set. + * Read more: "ELF for the Arm® 64-bit Architecture" + */ +#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) +# define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has BTI +# define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' +# define AARCH64_VALID_JUMP_TARGET hint #38 // BTI 'j' +#else +# define GNU_PROPERTY_AARCH64_BTI 0 // No BTI +# define AARCH64_VALID_CALL_TARGET +# define AARCH64_VALID_JUMP_TARGET +#endif + +#if (GNU_PROPERTY_AARCH64_BTI != 0) + .pushsection .note.gnu.property, "a" + .balign 8 + .long 4 + .long 0x10 + .long 0x5 + .asciz "GNU" + .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4 + .long GNU_PROPERTY_AARCH64_BTI + .long 0 + .popsection +#endif + .macro function name, export=0, align=2 .macro endfunc ELF .size \name, . - \name @@ -49,6 +78,7 @@ FUNC .endfunc ELF .type EXTERN_ASM\name, %function FUNC .func EXTERN_ASM\name EXTERN_ASM\name: + AARCH64_VALID_CALL_TARGET .else ELF .type \name, %function FUNC .func \name From d401b1cceceacc93c90f6d239dd58e22632c013d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 Nov 2021 00:17:10 +0100 Subject: [PATCH 177/894] avfilter: add colorspectrum source video filter --- Changelog | 1 + doc/filters.texi | 15 ++++++- libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 4 +- libavfilter/vsrc_testsrc.c | 92 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 111 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index 765ec82915..31a0d5ef5d 100644 --- a/Changelog +++ b/Changelog @@ -30,6 +30,7 @@ version : - xcorrelate video filter - varblur video filter - huesaturation video filter +- colorspectrum source video filter version 4.4: diff --git a/doc/filters.texi b/doc/filters.texi index b4f888c14d..c3ccaf97c4 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -25257,6 +25257,7 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c @anchor{allrgb} @anchor{allyuv} @anchor{color} +@anchor{colorspectrum} @anchor{haldclutsrc} @anchor{nullsrc} @anchor{pal75bars} @@ -25267,7 +25268,7 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c @anchor{testsrc} @anchor{testsrc2} @anchor{yuvtestsrc} -@section allrgb, allyuv, color, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc +@section allrgb, allyuv, color, colorspectrum, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc The @code{allrgb} source returns frames of size 4096x4096 of all rgb colors. @@ -25275,6 +25276,8 @@ The @code{allyuv} source returns frames of size 4096x4096 of all yuv colors. The @code{color} source provides an uniformly colored input. +The @code{colorspectrum} source provides a color spectrum input. + The @code{haldclutsrc} source provides an identity Hald CLUT. See also @ref{haldclut} filter. @@ -25366,6 +25369,16 @@ Set the number of decimals to show in the timestamp, only available in the The displayed timestamp value will correspond to the original timestamp value multiplied by the power of 10 of the specified value. Default value is 0. + +@item type +Set the type of the color spectrum, only available in the +@code{colorspectrum} source. Can be one of the following: + +@table @samp +@item black +@item white +@item all +@end table @end table @subsection Examples diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 08edc92d8c..07b4a639ec 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -522,6 +522,7 @@ OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_CELLAUTO_FILTER) += vsrc_cellauto.o OBJS-$(CONFIG_COLOR_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_COLORSPECTRUM_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_COREIMAGESRC_FILTER) += vf_coreimage.o OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o OBJS-$(CONFIG_GRADIENTS_FILTER) += vsrc_gradients.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index f250020159..29da7ef0d2 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -498,6 +498,7 @@ extern const AVFilter ff_vsrc_allrgb; extern const AVFilter ff_vsrc_allyuv; extern const AVFilter ff_vsrc_cellauto; extern const AVFilter ff_vsrc_color; +extern const AVFilter ff_vsrc_colorspectrum; extern const AVFilter ff_vsrc_coreimagesrc; extern const AVFilter ff_vsrc_frei0r_src; extern const AVFilter ff_vsrc_gradients; diff --git a/libavfilter/version.h b/libavfilter/version.h index 0912af7afe..b9e610ea1f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 16 -#define LIBAVFILTER_VERSION_MICRO 102 +#define LIBAVFILTER_VERSION_MINOR 17 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 6f48a8f86c..20b915d472 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -70,6 +70,9 @@ typedef struct TestSourceContext { /* only used by testsrc2 */ int alpha; + /* only used by colorspectrum */ + int type; + /* only used by color */ FFDrawContext draw; FFDrawColor color; @@ -1791,3 +1794,92 @@ const AVFilter ff_vsrc_allrgb = { }; #endif /* CONFIG_ALLRGB_FILTER */ + +#if CONFIG_COLORSPECTRUM_FILTER + +static const AVOption colorspectrum_options[] = { + COMMON_OPTIONS + { "type", "set the color spectrum type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "type" }, + { "black","fade to black", 0, AV_OPT_TYPE_CONST,{.i64=0},0, 0, FLAGS, "type" }, + { "white","fade to white", 0, AV_OPT_TYPE_CONST,{.i64=1},0, 0, FLAGS, "type" }, + { "all", "white to black", 0, AV_OPT_TYPE_CONST,{.i64=2},0, 0, FLAGS, "type" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorspectrum); + +static inline float mix(float a, float b, float mix) +{ + return a * mix + b * (1.f - mix); +} + +static void hsb2rgb(const float *c, float *rgb) +{ + rgb[0] = av_clipf(fabsf(fmodf(c[0] * 6.f + 0.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[1] = av_clipf(fabsf(fmodf(c[0] * 6.f + 4.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[2] = av_clipf(fabsf(fmodf(c[0] * 6.f + 2.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[0] = mix(c[3], (rgb[0] * rgb[0] * (3.f - 2.f * rgb[0])), c[1]) * c[2]; + rgb[1] = mix(c[3], (rgb[1] * rgb[1] * (3.f - 2.f * rgb[1])), c[1]) * c[2]; + rgb[2] = mix(c[3], (rgb[2] * rgb[2] * (3.f - 2.f * rgb[2])), c[1]) * c[2]; +} + +static void colorspectrum_fill_picture(AVFilterContext *ctx, AVFrame *frame) +{ + TestSourceContext *test = ctx->priv; + const float w = frame->width - 1.f; + const float h = frame->height - 1.f; + float c[4]; + + for (int y = 0; y < frame->height; y++) { + float *r = (float *)(frame->data[2] + y * frame->linesize[2]); + float *g = (float *)(frame->data[0] + y * frame->linesize[0]); + float *b = (float *)(frame->data[1] + y * frame->linesize[1]); + const float yh = y / h; + + c[1] = test->type == 2 ? yh > 0.5f ? 2.f * (yh - 0.5f) : 1.f - 2.f * yh : test->type == 1 ? 1.f - yh : yh; + c[2] = 1.f; + c[3] = test->type == 1 ? 1.f : test->type == 2 ? (yh > 0.5f ? 0.f : 1.f): 0.f; + for (int x = 0; x < frame->width; x++) { + float rgb[3]; + + c[0] = x / w; + hsb2rgb(c, rgb); + + r[x] = rgb[0]; + g[x] = rgb[1]; + b[x] = rgb[2]; + } + } +} + +static av_cold int colorspectrum_init(AVFilterContext *ctx) +{ + TestSourceContext *test = ctx->priv; + + test->draw_once = 1; + test->fill_picture_fn = colorspectrum_fill_picture; + return init(ctx); +} + +static const AVFilterPad avfilter_vsrc_colorspectrum_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + }, +}; + +const AVFilter ff_vsrc_colorspectrum = { + .name = "colorspectrum", + .description = NULL_IF_CONFIG_SMALL("Generate colors spectrum."), + .priv_size = sizeof(TestSourceContext), + .priv_class = &colorspectrum_class, + .init = colorspectrum_init, + .uninit = uninit, + .activate = activate, + .inputs = NULL, + FILTER_OUTPUTS(avfilter_vsrc_colorspectrum_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRPF32), +}; + +#endif /* CONFIG_COLORSPECTRUM_FILTER */ From e95969c07e9eb83bacf7ffebbdbe2687879bf5b1 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Wed, 17 Nov 2021 11:04:15 +0800 Subject: [PATCH 178/894] avfilter/gblur_vulkan: fix memory leak Whether failed or not, the block of codes labeled with fail should be always run to ensure the av_free(kernel_def) is executed. Signed-off-by: Wu Jianhua --- libavfilter/vf_gblur_vulkan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index b9e2c4fbc7..d4f391b25d 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -296,8 +296,6 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) s->initialized = 1; - return 0; - fail: av_free(kernel_def); return err; From be43eacb7eeaaf4632a40db3fad5ffe44872e4c4 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 17 Nov 2021 13:04:54 +0800 Subject: [PATCH 179/894] avfilter/vf_gblur_vulkan: Fix use of uninitialized value Signed-off-by: Limin Wang --- libavfilter/vf_gblur_vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index d4f391b25d..16c8bbb189 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -124,7 +124,7 @@ static av_cold void init_gaussian_params(GBlurVulkanContext *s) static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { - int err; + int err = 0; char *kernel_def; uint8_t *kernel_mapped; FFSPIRVShader *shd; From 54e65aa38abb37d6af92551b7e3adf6785f631ec Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Wed, 17 Nov 2021 14:12:33 +0000 Subject: [PATCH 180/894] avutil: Add Dolby Vision RPU side data type Signed-off-by: Derek Buitenhuis --- doc/APIchanges | 3 +++ libavutil/frame.c | 1 + libavutil/frame.h | 7 +++++++ libavutil/version.h | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index ad57ae29d6..565f7e091e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-11-17 - xxxxxxxxxx - lavf 57.9.100 - frame.h + Add AV_FRAME_DATA_DOVI_RPU_BUFFER. + 2021-11-xx - xxxxxxxxxx - lavf 59.9.100 - avformat.h Add av_stream_get_class(). Schedule adding AVStream.av_class at libavformat major version 60. diff --git a/libavutil/frame.c b/libavutil/frame.c index 2617cda2b5..d4d3ad6988 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -728,6 +728,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) case AV_FRAME_DATA_SEI_UNREGISTERED: return "H.26[45] User Data Unregistered SEI message"; case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters"; case AV_FRAME_DATA_DETECTION_BBOXES: return "Bounding boxes for object detection and classification"; + case AV_FRAME_DATA_DOVI_RPU_BUFFER: return "Dolby Vision RPU Data"; } return NULL; } diff --git a/libavutil/frame.h b/libavutil/frame.h index ff2540a20f..14097f0620 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -187,6 +187,13 @@ enum AVFrameSideDataType { * as described by AVDetectionBBoxHeader. */ AV_FRAME_DATA_DETECTION_BBOXES, + + /** + * Dolby Vision RPU data, suitable for passing to x265 + * or other libraries. Array of uint8_t, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_DOVI_RPU_BUFFER, }; enum AVActiveFormatDescription { diff --git a/libavutil/version.h b/libavutil/version.h index 5ebef06829..d94fb691d7 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 8 +#define LIBAVUTIL_VERSION_MINOR 9 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From bc68fd1050bd82e59d8ce7da909a0bcaf2b61197 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Thu, 22 Jul 2021 22:44:42 +0100 Subject: [PATCH 181/894] avcodec/hevcdec: Export Dolby Vision RPUs as side data Signed-off-by: Derek Buitenhuis --- libavcodec/hevcdec.c | 39 +++++++++++++++++++++++++++++++++++++++ libavcodec/hevcdec.h | 2 ++ libavcodec/version.h | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 246ffd7d80..3e19f4ebed 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2950,6 +2950,14 @@ static int set_side_data(HEVCContext *s) } } + if (s->rpu_buf) { + AVFrameSideData *rpu = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DOVI_RPU_BUFFER, s->rpu_buf); + if (!rpu) + return AVERROR(ENOMEM); + + s->rpu_buf = NULL; + } + return 0; } @@ -3223,6 +3231,7 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) break; case HEVC_NAL_AUD: case HEVC_NAL_FD_NUT: + case HEVC_NAL_UNSPEC62: break; default: av_log(s->avctx, AV_LOG_INFO, @@ -3269,6 +3278,29 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) } } + /* + * Check for RPU delimiter. + * + * Dolby Vision RPUs masquerade as unregistered NALs of type 62. + * + * We have to do this check here an create the rpu buffer, since RPUs are appended + * to the end of an AU; they are the last non-EOB/EOS NAL in the AU. + */ + if (s->pkt.nb_nals > 1 && s->pkt.nals[s->pkt.nb_nals - 1].type == HEVC_NAL_UNSPEC62 && + s->pkt.nals[s->pkt.nb_nals - 1].size > 2 && !s->pkt.nals[s->pkt.nb_nals - 1].nuh_layer_id + && !s->pkt.nals[s->pkt.nb_nals - 1].temporal_id) { + if (s->rpu_buf) { + av_buffer_unref(&s->rpu_buf); + av_log(s->avctx, AV_LOG_WARNING, "Multiple Dolby Vision RPUs found in one AU. Skipping previous.\n"); + } + + s->rpu_buf = av_buffer_alloc(s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); + if (!s->rpu_buf) + return AVERROR(ENOMEM); + + memcpy(s->rpu_buf->data, s->pkt.nals[s->pkt.nb_nals - 1].raw_data + 2, s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); + } + /* decode the NAL units */ for (i = 0; i < s->pkt.nb_nals; i++) { H2645NAL *nal = &s->pkt.nals[i]; @@ -3512,6 +3544,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) pic_arrays_free(s); + av_buffer_unref(&s->rpu_buf); + av_freep(&s->md5_ctx); av_freep(&s->cabac_state); @@ -3698,6 +3732,10 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (ret < 0) return ret; + ret = av_buffer_replace(&s->rpu_buf, s0->rpu_buf); + if (ret < 0) + return ret; + s->sei.frame_packing = s0->sei.frame_packing; s->sei.display_orientation = s0->sei.display_orientation; s->sei.mastering_display = s0->sei.mastering_display; @@ -3754,6 +3792,7 @@ static void hevc_decode_flush(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; ff_hevc_flush_dpb(s); ff_hevc_reset_sei(&s->sei); + av_buffer_unref(&s->rpu_buf); s->max_ra = INT_MAX; s->eos = 1; } diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 77fdf90da1..870ff178d4 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -572,6 +572,8 @@ typedef struct HEVCContext { int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) int nuh_layer_id; + + AVBufferRef *rpu_buf; ///< 0 or 1 Dolby Vision RPUs. } HEVCContext; /** diff --git a/libavcodec/version.h b/libavcodec/version.h index 7d4cfa3f11..4d3000364a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 12 +#define LIBAVCODEC_VERSION_MINOR 13 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 71fa14787bf1d30936421cbcc796ca1cb049aab9 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Wed, 20 Oct 2021 20:05:38 +0100 Subject: [PATCH 182/894] fate: Add test for Dolby Vision RPU side data Signed-off-by: Derek Buitenhuis --- tests/fate/hevc.mak | 3 + tests/ref/fate/hevc-dv-rpu | 512 +++++++++++++++++++++++++++++++++++++ 2 files changed, 515 insertions(+) create mode 100644 tests/ref/fate/hevc-dv-rpu diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index f6ea1df9a5..2a88eb4690 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -273,6 +273,9 @@ FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-monochrome-crop fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-hdr10-plus-metadata +fate-hevc-dv-rpu: CMD = probeframes -show_entries frame=side_data_list -select_streams 0 $(TARGET_SAMPLES)/hevc/dv84.mov +FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-dv-rpu + fate-hevc-two-first-slice: CMD = threads=2 framemd5 -i $(TARGET_SAMPLES)/hevc/two_first_slice.mp4 -sws_flags bitexact -t 00:02.00 -an FATE_HEVC-$(call DEMDEC, MOV, HEVC) += fate-hevc-two-first-slice diff --git a/tests/ref/fate/hevc-dv-rpu b/tests/ref/fate/hevc-dv-rpu new file mode 100644 index 0000000000..37ad9ffec2 --- /dev/null +++ b/tests/ref/fate/hevc-dv-rpu @@ -0,0 +1,512 @@ +[FRAME] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[/FRAME] From a35101aae36583450be4881a5cde2a904a489d84 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Tue, 26 Oct 2021 16:03:59 +0100 Subject: [PATCH 183/894] avformat/http: Add short_seek_size option In 45bfe8b838275235412777dd430206d9a24eb3ee, short_seek_threshold was removed from the public AVIO struct. Although this option was private and not intended to be used by public API users, it was nonetheless, because it provided functionality that could otherwise not be gained via public API. This was especially important for networked I/O like HTTP, where the internal size for lavf could be way to small depending on the specifics of a user's usecase, such as reading interlavd media files from cloud storage. Add an AVOption to make this functionality accessible to the HTTP client. Signed-off-by: Derek Buitenhuis --- libavformat/http.c | 4 ++++ libavformat/version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 476b9a8456..fdfbc69da1 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -126,6 +126,7 @@ typedef struct HTTPContext { int is_multi_client; HandshakeState handshake_step; int is_connected_server; + int short_seek_size; } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -167,6 +168,7 @@ static const AVOption options[] = { { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E }, { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E}, + { "short_seek_size", "Threshold to favor readahead over seek.", OFFSET(short_seek_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { NULL } }; @@ -1842,6 +1844,8 @@ static int http_get_file_handle(URLContext *h) static int http_get_short_seek(URLContext *h) { HTTPContext *s = h->priv_data; + if (s->short_seek_size >= 1) + return s->short_seek_size; return ffurl_get_short_seek(s->hd); } diff --git a/libavformat/version.h b/libavformat/version.h index 1d10481734..ae2b873197 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 #define LIBAVFORMAT_VERSION_MINOR 9 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 7596b6530d5f00ea0510b5c698714c76369811e7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Nov 2021 20:42:35 +0100 Subject: [PATCH 184/894] avformat/hlsenc: Remove nonsense memset The memset here is both unnecessary (avio_read() ignores the previous content of the destination buffer) as well as nonsense (for a char buf[BUFSIZE] sizeof(buf) and sizeof(BUFSIZE) are not the same; the latter is sizeof(int)). Fixes Coverity issue #1465863. Reviewed-by: Steven Liu Signed-off-by: Andreas Rheinhardt --- libavformat/hlsenc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 98608a834a..557cf1bee3 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2382,7 +2382,6 @@ static int64_t append_single_file(AVFormatContext *s, VariantStream *vs) } do { - memset(buf, 0, sizeof(BUFSIZE)); read_byte = avio_read(vs->out, buf, BUFSIZE); avio_write(vs->out_single_file, buf, read_byte); if (read_byte > 0) { From 96fe44e2e8e4c77e66cbb0834d340719741e964c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Nov 2021 22:21:37 +0100 Subject: [PATCH 185/894] avformat/hlsenc: Only write something if there is something to write This is especially important in case avio_write() would be switched to an unsigned type like size_t, then a potential error from avio_read() (with negative return value) would no longer be handled gracefully by avio_write(). Reviewed-by: Steven Liu Signed-off-by: Andreas Rheinhardt --- libavformat/hlsenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 557cf1bee3..cfd0c036d1 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2383,8 +2383,8 @@ static int64_t append_single_file(AVFormatContext *s, VariantStream *vs) do { read_byte = avio_read(vs->out, buf, BUFSIZE); - avio_write(vs->out_single_file, buf, read_byte); if (read_byte > 0) { + avio_write(vs->out_single_file, buf, read_byte); total_size += read_byte; ret = total_size; } From ea81c23c942088bf7099f176ac3cd0b993b64779 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 20:52:24 +0100 Subject: [PATCH 186/894] avformat/mxfenc: Remove redundant check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit None of the muxers here has the AVFMT_NOSTREAMS flag set, so it is checked generically that there are streams. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mxfenc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index c36ebef932..d84cb6dd29 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -2507,9 +2507,6 @@ static int mxf_write_header(AVFormatContext *s) uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0}; int64_t timestamp = 0; - if (!s->nb_streams) - return -1; - if (s->oformat == &ff_mxf_opatom_muxer && s->nb_streams !=1) { av_log(s, AV_LOG_ERROR, "there must be exactly one stream for mxf opatom\n"); return -1; From 5f4b0ace4be25e4d85b081c8d80b8748945a44c1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 20:58:27 +0100 Subject: [PATCH 187/894] avformat/mxfenc: Make init function out of write_header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MXF muxers only write the header after they have received a packet; the actual write_header function does not write anything. So make an init function out of it. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mxfenc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index d84cb6dd29..2f363917fc 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -2500,7 +2500,7 @@ static int mxf_init_timecode(AVFormatContext *s, AVStream *st, AVRational tbc) return av_timecode_init(&mxf->tc, av_inv_q(tbc), 0, 0, s); } -static int mxf_write_header(AVFormatContext *s) +static int mxf_init(AVFormatContext *s) { MXFContext *mxf = s->priv_data; int i, ret; @@ -3245,7 +3245,7 @@ const AVOutputFormat ff_mxf_muxer = { .priv_data_size = sizeof(MXFContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_MPEG2VIDEO, - .write_header = mxf_write_header, + .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, @@ -3261,7 +3261,7 @@ const AVOutputFormat ff_mxf_d10_muxer = { .priv_data_size = sizeof(MXFContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_MPEG2VIDEO, - .write_header = mxf_write_header, + .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, @@ -3278,7 +3278,7 @@ const AVOutputFormat ff_mxf_opatom_muxer = { .priv_data_size = sizeof(MXFContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_DNXHD, - .write_header = mxf_write_header, + .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, From 419d93c379bb6834529ec7e65a18ce4982c864aa Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 8 Nov 2021 15:03:52 +0100 Subject: [PATCH 188/894] avformat/utils: Remove unused shorthand feature for auto-inserted BSF Besides being unused it should not be used at all: The order of options of bitstream filters is not guaranteed to be stable at all. Signed-off-by: Andreas Rheinhardt --- libavformat/utils.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index a8611f5877..6eac3f721e 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1800,13 +1800,7 @@ int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *a } if (args && bsfc->filter->priv_class) { - const AVOption *opt = av_opt_next(bsfc->priv_data, NULL); - const char * shorthand[2] = {NULL}; - - if (opt) - shorthand[0] = opt->name; - - if ((ret = av_opt_set_from_string(bsfc->priv_data, args, shorthand, "=", ":")) < 0) { + if ((ret = av_set_options_string(bsfc->priv_data, args, "=", ":")) < 0) { av_bsf_free(&bsfc); return ret; } From 85a6b7f7b746a7bf71146b1530f19f699c4f0fb4 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 17 Nov 2021 15:41:02 +0100 Subject: [PATCH 189/894] vulkan_loader: fix typo in error message --- libavutil/vulkan_loader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index d4e05e62d7..3f1ee6aa46 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -121,7 +121,7 @@ static inline int ff_vk_load_functions(AVHWDeviceContext *ctx, } if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) { - av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated" + av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated " "as supported, but got NULL function pointer!\n", load->names[0]); return AVERROR_EXTERNAL; } From e5367b481b5232182a4851dbd7fc5a7a5bd475de Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 25 Aug 2021 13:08:10 +0200 Subject: [PATCH 190/894] ffmpeg: fix loosing gaps between audio frame timestamps when filtering --- fftools/ffmpeg.c | 5 + fftools/ffmpeg.h | 1 + fftools/ffmpeg_opt.c | 1 + tests/ref/fate/adpcm-ima-smjpeg | 658 ++++++++++++++++---------------- tests/ref/fate/dcinema-encode | 26 +- tests/ref/lavf/smjpeg | 2 +- 6 files changed, 350 insertions(+), 343 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 7b2dcee838..b1d2c69fa7 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2382,6 +2382,11 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, decoded_frame->pts = ist->dts; decoded_frame_tb = AV_TIME_BASE_Q; } + if (pkt && pkt->duration && ist->prev_pkt_pts != AV_NOPTS_VALUE && + pkt->pts != AV_NOPTS_VALUE && pkt->pts - ist->prev_pkt_pts > pkt->duration) + ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + if (pkt) + ist->prev_pkt_pts = pkt->pts; if (decoded_frame->pts != AV_NOPTS_VALUE) decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, (AVRational){1, avctx->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 30225e9ffe..545ff1c8e7 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -314,6 +314,7 @@ typedef struct InputStream { AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ AVPacket *pkt; + int64_t prev_pkt_pts; int64_t start; /* time when read started */ /* predicted dts of the next packet read for this stream or (when there are * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 4685cf6435..ce8bae0775 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -875,6 +875,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + ist->prev_pkt_pts = AV_NOPTS_VALUE; ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) { diff --git a/tests/ref/fate/adpcm-ima-smjpeg b/tests/ref/fate/adpcm-ima-smjpeg index d56014ea01..a216e3ab5e 100644 --- a/tests/ref/fate/adpcm-ima-smjpeg +++ b/tests/ref/fate/adpcm-ima-smjpeg @@ -9,348 +9,348 @@ 0, 1024, 1024, 512, 1024, 0xed2d3f6b 0, 1533, 1533, 512, 1024, 0x51f6ccb3 0, 2040, 2040, 512, 1024, 0x58bd75aa -0, 2552, 2552, 512, 1024, 0xd857a310 -0, 3064, 3064, 512, 1024, 0xc483a5b8 -0, 3576, 3576, 512, 1024, 0x923ecf67 -0, 4088, 4088, 512, 1024, 0xf87dcd53 +0, 2558, 2558, 512, 1024, 0xd857a310 +0, 3070, 3070, 512, 1024, 0xc483a5b8 +0, 3582, 3582, 512, 1024, 0x923ecf67 +0, 4091, 4091, 512, 1024, 0xf87dcd53 0, 4598, 4598, 512, 1024, 0xdc32c002 -0, 5110, 5110, 512, 1024, 0xb760def1 -0, 5622, 5622, 512, 1024, 0x6838d2b2 -0, 6134, 6134, 512, 1024, 0xe45aca1e -0, 6646, 6646, 512, 1024, 0xde1fb955 -0, 7158, 7158, 512, 1024, 0x9e23b949 -0, 7670, 7670, 512, 1024, 0x840cc000 -0, 8182, 8182, 512, 1024, 0x0a29cbfa -0, 8694, 8694, 512, 1024, 0x9871d4c4 +0, 5116, 5116, 512, 1024, 0xb760def1 +0, 5628, 5628, 512, 1024, 0x6838d2b2 +0, 6140, 6140, 512, 1024, 0xe45aca1e +0, 6649, 6649, 512, 1024, 0xde1fb955 +0, 7166, 7166, 512, 1024, 0x9e23b949 +0, 7678, 7678, 512, 1024, 0x840cc000 +0, 8190, 8190, 512, 1024, 0x0a29cbfa +0, 8699, 8699, 512, 1024, 0x9871d4c4 0, 9206, 9206, 512, 1024, 0xb35dc9f2 -0, 9718, 9718, 512, 1024, 0xf37fda0a -0, 10230, 10230, 512, 1024, 0xa640f990 -0, 10742, 10742, 512, 1024, 0x516fe6f5 -0, 11254, 11254, 512, 1024, 0xc78bc6a6 -0, 11766, 11766, 512, 1024, 0x700fd6ee -0, 12278, 12278, 512, 1024, 0x5383d5ad -0, 12790, 12790, 512, 1024, 0xbe01d091 -0, 13302, 13302, 512, 1024, 0x72dfcfc7 -0, 13814, 13814, 512, 1024, 0xd8fecea9 -0, 14326, 14326, 512, 1024, 0xa464d79b -0, 14838, 14838, 512, 1024, 0xf394e2cb -0, 15350, 15350, 512, 1024, 0xa301ec49 -0, 15862, 15862, 512, 1024, 0x5e09d60f -0, 16374, 16374, 512, 1024, 0xd13edd6f -0, 16886, 16886, 512, 1024, 0x7423ef39 -0, 17398, 17398, 512, 1024, 0x96e2f083 -0, 17910, 17910, 512, 1024, 0x5ed7dbee -0, 18422, 18422, 512, 1024, 0x3874f714 -0, 18934, 18934, 512, 1024, 0xa5e6edab -0, 19446, 19446, 512, 1024, 0x0a04ee3a -0, 19958, 19958, 512, 1024, 0xadfee6b9 -0, 20470, 20470, 512, 1024, 0xd0bbe6d2 -0, 20982, 20982, 512, 1024, 0x223eebb7 -0, 21494, 21494, 512, 1024, 0x0473e479 -0, 22006, 22006, 512, 1024, 0xdf15e51e -0, 22518, 22518, 512, 1024, 0xa954e483 -0, 23030, 23030, 512, 1024, 0x6df3ed03 -0, 23542, 23542, 512, 1024, 0x0860e544 -0, 24054, 24054, 512, 1024, 0xc241e8dc -0, 24566, 24566, 512, 1024, 0xd0e1d6a4 -0, 25078, 25078, 512, 1024, 0xcb2ff988 +0, 9724, 9724, 512, 1024, 0xf37fda0a +0, 10236, 10236, 512, 1024, 0xa640f990 +0, 10748, 10748, 512, 1024, 0x516fe6f5 +0, 11257, 11257, 512, 1024, 0xc78bc6a6 +0, 11775, 11775, 512, 1024, 0x700fd6ee +0, 12287, 12287, 512, 1024, 0x5383d5ad +0, 12799, 12799, 512, 1024, 0xbe01d091 +0, 13308, 13308, 512, 1024, 0x72dfcfc7 +0, 13815, 13815, 512, 1024, 0xd8fecea9 +0, 14333, 14333, 512, 1024, 0xa464d79b +0, 14845, 14845, 512, 1024, 0xf394e2cb +0, 15357, 15357, 512, 1024, 0xa301ec49 +0, 15865, 15865, 512, 1024, 0x5e09d60f +0, 16383, 16383, 512, 1024, 0xd13edd6f +0, 16895, 16895, 512, 1024, 0x7423ef39 +0, 17407, 17407, 512, 1024, 0x96e2f083 +0, 17916, 17916, 512, 1024, 0x5ed7dbee +0, 18423, 18423, 512, 1024, 0x3874f714 +0, 18941, 18941, 512, 1024, 0xa5e6edab +0, 19453, 19453, 512, 1024, 0x0a04ee3a +0, 19965, 19965, 512, 1024, 0xadfee6b9 +0, 20474, 20474, 512, 1024, 0xd0bbe6d2 +0, 20992, 20992, 512, 1024, 0x223eebb7 +0, 21504, 21504, 512, 1024, 0x0473e479 +0, 22016, 22016, 512, 1024, 0xdf15e51e +0, 22525, 22525, 512, 1024, 0xa954e483 +0, 23032, 23032, 512, 1024, 0x6df3ed03 +0, 23549, 23549, 512, 1024, 0x0860e544 +0, 24061, 24061, 512, 1024, 0xc241e8dc +0, 24573, 24573, 512, 1024, 0xd0e1d6a4 +0, 25082, 25082, 512, 1024, 0xcb2ff988 0, 25590, 25590, 512, 1024, 0x51fae08e -0, 26102, 26102, 512, 1024, 0xae39f2fc -0, 26614, 26614, 512, 1024, 0xfd74f07c -0, 27126, 27126, 512, 1024, 0x1936edc1 -0, 27638, 27638, 512, 1024, 0x95f8deae -0, 28150, 28150, 512, 1024, 0x93bdf605 -0, 28662, 28662, 512, 1024, 0x7a07dd32 -0, 29174, 29174, 512, 1024, 0x6889fdc1 -0, 29686, 29686, 512, 1024, 0x989bf024 +0, 26107, 26107, 512, 1024, 0xae39f2fc +0, 26619, 26619, 512, 1024, 0xfd74f07c +0, 27131, 27131, 512, 1024, 0x1936edc1 +0, 27640, 27640, 512, 1024, 0x95f8deae +0, 28158, 28158, 512, 1024, 0x93bdf605 +0, 28670, 28670, 512, 1024, 0x7a07dd32 +0, 29182, 29182, 512, 1024, 0x6889fdc1 +0, 29691, 29691, 512, 1024, 0x989bf024 0, 30198, 30198, 512, 1024, 0xc764ce80 -0, 30710, 30710, 512, 1024, 0x0e62d721 -0, 31222, 31222, 512, 1024, 0x59c2fbe3 -0, 31734, 31734, 512, 1024, 0xf14ee29d -0, 32246, 32246, 512, 1024, 0x02a0f21b -0, 32758, 32758, 512, 1024, 0xadb3d361 -0, 33270, 33270, 512, 1024, 0xdcb3d1fc -0, 33782, 33782, 512, 1024, 0x2924f9dc -0, 34294, 34294, 512, 1024, 0x7507ebec +0, 30716, 30716, 512, 1024, 0x0e62d721 +0, 31228, 31228, 512, 1024, 0x59c2fbe3 +0, 31740, 31740, 512, 1024, 0xf14ee29d +0, 32249, 32249, 512, 1024, 0x02a0f21b +0, 32766, 32766, 512, 1024, 0xadb3d361 +0, 33278, 33278, 512, 1024, 0xdcb3d1fc +0, 33790, 33790, 512, 1024, 0x2924f9dc +0, 34299, 34299, 512, 1024, 0x7507ebec 0, 34806, 34806, 512, 1024, 0xe009f343 -0, 35318, 35318, 512, 1024, 0x21e9e7ac -0, 35830, 35830, 512, 1024, 0x845bda9e -0, 36342, 36342, 512, 1024, 0xb1b3e632 -0, 36854, 36854, 512, 1024, 0x61ccf593 -0, 37366, 37366, 512, 1024, 0x8cdbf603 -0, 37878, 37878, 512, 1024, 0xf8f7e673 -0, 38390, 38390, 512, 1024, 0x55efdd24 -0, 38902, 38902, 512, 1024, 0x4059e8ff -0, 39414, 39414, 512, 1024, 0xb3afe5be -0, 39926, 39926, 512, 1024, 0x7236e965 -0, 40438, 40438, 512, 1024, 0xe683db69 -0, 40950, 40950, 512, 1024, 0x29e3d93c -0, 41462, 41462, 512, 1024, 0x74f2f27f -0, 41974, 41974, 512, 1024, 0x32cde3ba -0, 42486, 42486, 512, 1024, 0xe907f171 -0, 42998, 42998, 512, 1024, 0x206ae2a5 -0, 43510, 43510, 512, 1024, 0x6379efa1 -0, 44022, 44022, 512, 1024, 0x0f0fee85 -0, 44534, 44534, 512, 1024, 0x3195e314 -0, 45046, 45046, 512, 1024, 0x4646ead3 -0, 45558, 45558, 512, 1024, 0x5635dcf5 -0, 46070, 46070, 512, 1024, 0xd76fc780 -0, 46582, 46582, 512, 1024, 0x847ff8a5 -0, 47094, 47094, 512, 1024, 0xaca8eda3 -0, 47606, 47606, 512, 1024, 0x9a2de1ea -0, 48118, 48118, 512, 1024, 0xc92ff23a -0, 48630, 48630, 512, 1024, 0x0e0ef038 -0, 49142, 49142, 512, 1024, 0xc32cf495 -0, 49654, 49654, 512, 1024, 0x6ab1ec79 -0, 50166, 50166, 512, 1024, 0xe43cd8d6 -0, 50678, 50678, 512, 1024, 0x4ba2deab +0, 35324, 35324, 512, 1024, 0x21e9e7ac +0, 35836, 35836, 512, 1024, 0x845bda9e +0, 36348, 36348, 512, 1024, 0xb1b3e632 +0, 36857, 36857, 512, 1024, 0x61ccf593 +0, 37375, 37375, 512, 1024, 0x8cdbf603 +0, 37887, 37887, 512, 1024, 0xf8f7e673 +0, 38399, 38399, 512, 1024, 0x55efdd24 +0, 38908, 38908, 512, 1024, 0x4059e8ff +0, 39415, 39415, 512, 1024, 0xb3afe5be +0, 39933, 39933, 512, 1024, 0x7236e965 +0, 40445, 40445, 512, 1024, 0xe683db69 +0, 40957, 40957, 512, 1024, 0x29e3d93c +0, 41466, 41466, 512, 1024, 0x74f2f27f +0, 41983, 41983, 512, 1024, 0x32cde3ba +0, 42495, 42495, 512, 1024, 0xe907f171 +0, 43007, 43007, 512, 1024, 0x206ae2a5 +0, 43516, 43516, 512, 1024, 0x6379efa1 +0, 44023, 44023, 512, 1024, 0x0f0fee85 +0, 44541, 44541, 512, 1024, 0x3195e314 +0, 45053, 45053, 512, 1024, 0x4646ead3 +0, 45565, 45565, 512, 1024, 0x5635dcf5 +0, 46074, 46074, 512, 1024, 0xd76fc780 +0, 46592, 46592, 512, 1024, 0x847ff8a5 +0, 47104, 47104, 512, 1024, 0xaca8eda3 +0, 47616, 47616, 512, 1024, 0x9a2de1ea +0, 48125, 48125, 512, 1024, 0xc92ff23a +0, 48632, 48632, 512, 1024, 0x0e0ef038 +0, 49149, 49149, 512, 1024, 0xc32cf495 +0, 49661, 49661, 512, 1024, 0x6ab1ec79 +0, 50173, 50173, 512, 1024, 0xe43cd8d6 +0, 50682, 50682, 512, 1024, 0x4ba2deab 0, 51190, 51190, 512, 1024, 0x6d16ea0e -0, 51702, 51702, 512, 1024, 0xe5b0ee70 -0, 52214, 52214, 512, 1024, 0xcf6cf074 -0, 52726, 52726, 512, 1024, 0x2206e61d -0, 53238, 53238, 512, 1024, 0xfbb9e7e7 -0, 53750, 53750, 512, 1024, 0x2bc1e115 -0, 54262, 54262, 512, 1024, 0x4ca6e5c5 -0, 54774, 54774, 512, 1024, 0x061cead0 -0, 55286, 55286, 512, 1024, 0x3dc9f950 +0, 51707, 51707, 512, 1024, 0xe5b0ee70 +0, 52219, 52219, 512, 1024, 0xcf6cf074 +0, 52731, 52731, 512, 1024, 0x2206e61d +0, 53240, 53240, 512, 1024, 0xfbb9e7e7 +0, 53758, 53758, 512, 1024, 0x2bc1e115 +0, 54270, 54270, 512, 1024, 0x4ca6e5c5 +0, 54782, 54782, 512, 1024, 0x061cead0 +0, 55291, 55291, 512, 1024, 0x3dc9f950 0, 55798, 55798, 512, 1024, 0x9399f10d -0, 56310, 56310, 512, 1024, 0xa2bff5ae -0, 56822, 56822, 512, 1024, 0xd21de569 -0, 57334, 57334, 512, 1024, 0x1c45e3be -0, 57846, 57846, 512, 1024, 0xff5dff1c -0, 58358, 58358, 512, 1024, 0x992df5d3 -0, 58870, 58870, 512, 1024, 0xafedea2f -0, 59382, 59382, 512, 1024, 0x6e73d6a8 -0, 59894, 59894, 512, 1024, 0x72dff283 +0, 56316, 56316, 512, 1024, 0xa2bff5ae +0, 56828, 56828, 512, 1024, 0xd21de569 +0, 57340, 57340, 512, 1024, 0x1c45e3be +0, 57849, 57849, 512, 1024, 0xff5dff1c +0, 58366, 58366, 512, 1024, 0x992df5d3 +0, 58878, 58878, 512, 1024, 0xafedea2f +0, 59390, 59390, 512, 1024, 0x6e73d6a8 +0, 59899, 59899, 512, 1024, 0x72dff283 0, 60406, 60406, 512, 1024, 0x50b5f1a6 -0, 60918, 60918, 512, 1024, 0xffe1decb -0, 61430, 61430, 512, 1024, 0x8993ecff -0, 61942, 61942, 512, 1024, 0x954bd63a -0, 62454, 62454, 512, 1024, 0x4707f577 -0, 62966, 62966, 512, 1024, 0x7a88f81f -0, 63478, 63478, 512, 1024, 0xc771f537 -0, 63990, 63990, 512, 1024, 0x7aade6af -0, 64502, 64502, 512, 1024, 0x8af5ede5 -0, 65014, 65014, 512, 1024, 0x7500f3f1 -0, 65526, 65526, 512, 1024, 0xea36f707 -0, 66038, 66038, 512, 1024, 0x1a26e39a -0, 66550, 66550, 512, 1024, 0xa04cf00d -0, 67062, 67062, 512, 1024, 0xc362f182 -0, 67574, 67574, 512, 1024, 0x79c8f82c -0, 68086, 68086, 512, 1024, 0x6480eee1 -0, 68598, 68598, 512, 1024, 0x7152eaa0 -0, 69110, 69110, 512, 1024, 0x5dfee6a9 -0, 69622, 69622, 512, 1024, 0x0afae660 -0, 70134, 70134, 512, 1024, 0xdc98e9fc -0, 70646, 70646, 512, 1024, 0x10b7da06 -0, 71158, 71158, 512, 1024, 0x0571e585 -0, 71670, 71670, 512, 1024, 0x18ddf45e -0, 72182, 72182, 512, 1024, 0x2cbef242 -0, 72694, 72694, 512, 1024, 0xf5380845 -0, 73206, 73206, 512, 1024, 0x34fff45e -0, 73718, 73718, 512, 1024, 0x6f97e490 -0, 74230, 74230, 512, 1024, 0x77d6f0db -0, 74742, 74742, 512, 1024, 0xa25ce2db -0, 75254, 75254, 512, 1024, 0x8260e4e9 -0, 75766, 75766, 512, 1024, 0xc3b2f7d2 -0, 76278, 76278, 512, 1024, 0x82a7edae +0, 60924, 60924, 512, 1024, 0xffe1decb +0, 61436, 61436, 512, 1024, 0x8993ecff +0, 61948, 61948, 512, 1024, 0x954bd63a +0, 62457, 62457, 512, 1024, 0x4707f577 +0, 62975, 62975, 512, 1024, 0x7a88f81f +0, 63487, 63487, 512, 1024, 0xc771f537 +0, 63999, 63999, 512, 1024, 0x7aade6af +0, 64508, 64508, 512, 1024, 0x8af5ede5 +0, 65015, 65015, 512, 1024, 0x7500f3f1 +0, 65533, 65533, 512, 1024, 0xea36f707 +0, 66045, 66045, 512, 1024, 0x1a26e39a +0, 66557, 66557, 512, 1024, 0xa04cf00d +0, 67066, 67066, 512, 1024, 0xc362f182 +0, 67583, 67583, 512, 1024, 0x79c8f82c +0, 68095, 68095, 512, 1024, 0x6480eee1 +0, 68607, 68607, 512, 1024, 0x7152eaa0 +0, 69116, 69116, 512, 1024, 0x5dfee6a9 +0, 69623, 69623, 512, 1024, 0x0afae660 +0, 70141, 70141, 512, 1024, 0xdc98e9fc +0, 70653, 70653, 512, 1024, 0x10b7da06 +0, 71165, 71165, 512, 1024, 0x0571e585 +0, 71674, 71674, 512, 1024, 0x18ddf45e +0, 72192, 72192, 512, 1024, 0x2cbef242 +0, 72704, 72704, 512, 1024, 0xf5380845 +0, 73216, 73216, 512, 1024, 0x34fff45e +0, 73725, 73725, 512, 1024, 0x6f97e490 +0, 74232, 74232, 512, 1024, 0x77d6f0db +0, 74750, 74750, 512, 1024, 0xa25ce2db +0, 75262, 75262, 512, 1024, 0x8260e4e9 +0, 75774, 75774, 512, 1024, 0xc3b2f7d2 +0, 76282, 76282, 512, 1024, 0x82a7edae 0, 76790, 76790, 512, 1024, 0x7d08dd54 -0, 77302, 77302, 512, 1024, 0x9059eda6 -0, 77814, 77814, 512, 1024, 0xbebaec88 -0, 78326, 78326, 512, 1024, 0xd9afd586 -0, 78838, 78838, 512, 1024, 0x0ca3e622 -0, 79350, 79350, 512, 1024, 0x4123e9e6 -0, 79862, 79862, 512, 1024, 0x2ff9f95c -0, 80374, 80374, 512, 1024, 0x8522e261 -0, 80886, 80886, 512, 1024, 0xe4f8f499 +0, 77307, 77307, 512, 1024, 0x9059eda6 +0, 77819, 77819, 512, 1024, 0xbebaec88 +0, 78331, 78331, 512, 1024, 0xd9afd586 +0, 78840, 78840, 512, 1024, 0x0ca3e622 +0, 79358, 79358, 512, 1024, 0x4123e9e6 +0, 79870, 79870, 512, 1024, 0x2ff9f95c +0, 80382, 80382, 512, 1024, 0x8522e261 +0, 80891, 80891, 512, 1024, 0xe4f8f499 0, 81398, 81398, 512, 1024, 0x34f3f2bd -0, 81910, 81910, 512, 1024, 0x82efe863 -0, 82422, 82422, 512, 1024, 0x9966fcea -0, 82934, 82934, 512, 1024, 0xe94de3fd -0, 83446, 83446, 512, 1024, 0x1ce0e27b -0, 83958, 83958, 512, 1024, 0xd718dcde -0, 84470, 84470, 512, 1024, 0xd503e724 -0, 84982, 84982, 512, 1024, 0x427ee3b2 -0, 85494, 85494, 512, 1024, 0x4512dcc4 -0, 86006, 86006, 512, 1024, 0xcf31e77c -0, 86518, 86518, 512, 1024, 0xeb41ea81 -0, 87030, 87030, 512, 1024, 0xfa43e67c -0, 87542, 87542, 512, 1024, 0x8162f3c9 -0, 88054, 88054, 512, 1024, 0x1b55f6b0 -0, 88566, 88566, 512, 1024, 0x3ebeec44 -0, 89078, 89078, 512, 1024, 0x740fe0c4 -0, 89590, 89590, 512, 1024, 0x8fb4e8b2 -0, 90102, 90102, 512, 1024, 0xe49de6a2 -0, 90614, 90614, 512, 1024, 0xd64febdf -0, 91126, 91126, 512, 1024, 0x0e74ee08 -0, 91638, 91638, 512, 1024, 0x6c0ddf07 -0, 92150, 92150, 512, 1024, 0x7fb8e3c9 -0, 92662, 92662, 512, 1024, 0x52bfe96c -0, 93174, 93174, 512, 1024, 0xfc22ee64 -0, 93686, 93686, 512, 1024, 0xe20ae718 -0, 94198, 94198, 512, 1024, 0xa94be395 -0, 94710, 94710, 512, 1024, 0xded306d0 -0, 95222, 95222, 512, 1024, 0x31f7c831 -0, 95734, 95734, 512, 1024, 0x0ffde0a8 -0, 96246, 96246, 512, 1024, 0xc692e3e0 -0, 96758, 96758, 512, 1024, 0x1d8ff7c7 -0, 97270, 97270, 512, 1024, 0x038ee172 -0, 97782, 97782, 512, 1024, 0x9a1eef59 -0, 98294, 98294, 512, 1024, 0x158fe750 -0, 98806, 98806, 512, 1024, 0xac15e42c -0, 99318, 99318, 512, 1024, 0x6323ed44 -0, 99830, 99830, 512, 1024, 0xd10ce4bb -0, 100342, 100342, 512, 1024, 0xc1cce296 -0, 100854, 100854, 512, 1024, 0x0782f094 -0, 101366, 101366, 512, 1024, 0xd109de36 -0, 101878, 101878, 512, 1024, 0x175600fb +0, 81916, 81916, 512, 1024, 0x82efe863 +0, 82428, 82428, 512, 1024, 0x9966fcea +0, 82940, 82940, 512, 1024, 0xe94de3fd +0, 83449, 83449, 512, 1024, 0x1ce0e27b +0, 83966, 83966, 512, 1024, 0xd718dcde +0, 84478, 84478, 512, 1024, 0xd503e724 +0, 84990, 84990, 512, 1024, 0x427ee3b2 +0, 85499, 85499, 512, 1024, 0x4512dcc4 +0, 86007, 86007, 512, 1024, 0xcf31e77c +0, 86524, 86524, 512, 1024, 0xeb41ea81 +0, 87036, 87036, 512, 1024, 0xfa43e67c +0, 87548, 87548, 512, 1024, 0x8162f3c9 +0, 88057, 88057, 512, 1024, 0x1b55f6b0 +0, 88575, 88575, 512, 1024, 0x3ebeec44 +0, 89087, 89087, 512, 1024, 0x740fe0c4 +0, 89599, 89599, 512, 1024, 0x8fb4e8b2 +0, 90108, 90108, 512, 1024, 0xe49de6a2 +0, 90615, 90615, 512, 1024, 0xd64febdf +0, 91133, 91133, 512, 1024, 0x0e74ee08 +0, 91645, 91645, 512, 1024, 0x6c0ddf07 +0, 92157, 92157, 512, 1024, 0x7fb8e3c9 +0, 92666, 92666, 512, 1024, 0x52bfe96c +0, 93183, 93183, 512, 1024, 0xfc22ee64 +0, 93695, 93695, 512, 1024, 0xe20ae718 +0, 94207, 94207, 512, 1024, 0xa94be395 +0, 94716, 94716, 512, 1024, 0xded306d0 +0, 95223, 95223, 512, 1024, 0x31f7c831 +0, 95741, 95741, 512, 1024, 0x0ffde0a8 +0, 96253, 96253, 512, 1024, 0xc692e3e0 +0, 96765, 96765, 512, 1024, 0x1d8ff7c7 +0, 97274, 97274, 512, 1024, 0x038ee172 +0, 97792, 97792, 512, 1024, 0x9a1eef59 +0, 98304, 98304, 512, 1024, 0x158fe750 +0, 98816, 98816, 512, 1024, 0xac15e42c +0, 99325, 99325, 512, 1024, 0x6323ed44 +0, 99832, 99832, 512, 1024, 0xd10ce4bb +0, 100350, 100350, 512, 1024, 0xc1cce296 +0, 100862, 100862, 512, 1024, 0x0782f094 +0, 101374, 101374, 512, 1024, 0xd109de36 +0, 101883, 101883, 512, 1024, 0x175600fb 0, 102390, 102390, 512, 1024, 0x95d5e8d9 -0, 102902, 102902, 512, 1024, 0xebb6eee1 -0, 103414, 103414, 512, 1024, 0x187cfadc -0, 103926, 103926, 512, 1024, 0xce35fa5c -0, 104438, 104438, 512, 1024, 0x8327eea2 -0, 104950, 104950, 512, 1024, 0x5543f219 -0, 105462, 105462, 512, 1024, 0xaacbe0dc -0, 105974, 105974, 512, 1024, 0xa538e9fb -0, 106486, 106486, 512, 1024, 0x4dcbe655 +0, 102907, 102907, 512, 1024, 0xebb6eee1 +0, 103419, 103419, 512, 1024, 0x187cfadc +0, 103931, 103931, 512, 1024, 0xce35fa5c +0, 104440, 104440, 512, 1024, 0x8327eea2 +0, 104958, 104958, 512, 1024, 0x5543f219 +0, 105470, 105470, 512, 1024, 0xaacbe0dc +0, 105982, 105982, 512, 1024, 0xa538e9fb +0, 106491, 106491, 512, 1024, 0x4dcbe655 0, 106998, 106998, 512, 1024, 0x86b6d93b -0, 107510, 107510, 512, 1024, 0x1a06f878 -0, 108022, 108022, 512, 1024, 0xd926e8ef -0, 108534, 108534, 512, 1024, 0xc624db2f -0, 109046, 109046, 512, 1024, 0x2153e20d -0, 109558, 109558, 512, 1024, 0x01dce868 -0, 110070, 110070, 512, 1024, 0xfa5fd3cd -0, 110582, 110582, 512, 1024, 0x2adef2d5 -0, 111094, 111094, 512, 1024, 0x4f48f8e2 -0, 111606, 111606, 512, 1024, 0x613feeee -0, 112118, 112118, 512, 1024, 0x3780de8a -0, 112630, 112630, 512, 1024, 0x2093eb65 -0, 113142, 113142, 512, 1024, 0x54baebbb -0, 113654, 113654, 512, 1024, 0x8686dd7c -0, 114166, 114166, 512, 1024, 0x7f8ae80c -0, 114678, 114678, 512, 1024, 0x7aede972 -0, 115190, 115190, 512, 1024, 0x971bebc0 -0, 115702, 115702, 512, 1024, 0x2dd5fd4b -0, 116214, 116214, 512, 1024, 0xb1b3e4a3 -0, 116726, 116726, 512, 1024, 0x192defc6 -0, 117238, 117238, 512, 1024, 0x5e46ec44 -0, 117750, 117750, 512, 1024, 0xe6d8e05a -0, 118262, 118262, 512, 1024, 0x7e2fe2b0 -0, 118774, 118774, 512, 1024, 0x9e3bdf80 -0, 119286, 119286, 512, 1024, 0xa98cd85e -0, 119798, 119798, 512, 1024, 0x6061e0c4 -0, 120310, 120310, 512, 1024, 0x6112f3fc -0, 120822, 120822, 512, 1024, 0x99bdfb01 -0, 121334, 121334, 512, 1024, 0x3f5df3ca -0, 121846, 121846, 512, 1024, 0xf5ebeb05 -0, 122358, 122358, 512, 1024, 0x8498e565 -0, 122870, 122870, 512, 1024, 0x0497f0b7 -0, 123382, 123382, 512, 1024, 0x626ae800 -0, 123894, 123894, 512, 1024, 0xfb71eec4 -0, 124406, 124406, 512, 1024, 0xa86ee739 -0, 124918, 124918, 512, 1024, 0x25c0e050 -0, 125430, 125430, 512, 1024, 0x6027e91e -0, 125942, 125942, 512, 1024, 0x6772df6e -0, 126454, 126454, 512, 1024, 0xfefff844 -0, 126966, 126966, 512, 1024, 0x547be862 -0, 127478, 127478, 512, 1024, 0xca84e795 +0, 107516, 107516, 512, 1024, 0x1a06f878 +0, 108028, 108028, 512, 1024, 0xd926e8ef +0, 108540, 108540, 512, 1024, 0xc624db2f +0, 109049, 109049, 512, 1024, 0x2153e20d +0, 109566, 109566, 512, 1024, 0x01dce868 +0, 110078, 110078, 512, 1024, 0xfa5fd3cd +0, 110590, 110590, 512, 1024, 0x2adef2d5 +0, 111099, 111099, 512, 1024, 0x4f48f8e2 +0, 111607, 111607, 512, 1024, 0x613feeee +0, 112124, 112124, 512, 1024, 0x3780de8a +0, 112636, 112636, 512, 1024, 0x2093eb65 +0, 113148, 113148, 512, 1024, 0x54baebbb +0, 113657, 113657, 512, 1024, 0x8686dd7c +0, 114175, 114175, 512, 1024, 0x7f8ae80c +0, 114687, 114687, 512, 1024, 0x7aede972 +0, 115199, 115199, 512, 1024, 0x971bebc0 +0, 115708, 115708, 512, 1024, 0x2dd5fd4b +0, 116215, 116215, 512, 1024, 0xb1b3e4a3 +0, 116733, 116733, 512, 1024, 0x192defc6 +0, 117245, 117245, 512, 1024, 0x5e46ec44 +0, 117757, 117757, 512, 1024, 0xe6d8e05a +0, 118266, 118266, 512, 1024, 0x7e2fe2b0 +0, 118783, 118783, 512, 1024, 0x9e3bdf80 +0, 119295, 119295, 512, 1024, 0xa98cd85e +0, 119807, 119807, 512, 1024, 0x6061e0c4 +0, 120316, 120316, 512, 1024, 0x6112f3fc +0, 120823, 120823, 512, 1024, 0x99bdfb01 +0, 121341, 121341, 512, 1024, 0x3f5df3ca +0, 121853, 121853, 512, 1024, 0xf5ebeb05 +0, 122365, 122365, 512, 1024, 0x8498e565 +0, 122874, 122874, 512, 1024, 0x0497f0b7 +0, 123392, 123392, 512, 1024, 0x626ae800 +0, 123904, 123904, 512, 1024, 0xfb71eec4 +0, 124416, 124416, 512, 1024, 0xa86ee739 +0, 124925, 124925, 512, 1024, 0x25c0e050 +0, 125432, 125432, 512, 1024, 0x6027e91e +0, 125950, 125950, 512, 1024, 0x6772df6e +0, 126462, 126462, 512, 1024, 0xfefff844 +0, 126974, 126974, 512, 1024, 0x547be862 +0, 127483, 127483, 512, 1024, 0xca84e795 0, 127990, 127990, 512, 1024, 0xd124db3e -0, 128502, 128502, 512, 1024, 0xcaf3deb5 -0, 129014, 129014, 512, 1024, 0x487ce92d -0, 129526, 129526, 512, 1024, 0x117feb95 -0, 130038, 130038, 512, 1024, 0x7b63de3d -0, 130550, 130550, 512, 1024, 0xa529d8e1 -0, 131062, 131062, 512, 1024, 0x56f6da26 -0, 131574, 131574, 512, 1024, 0xffb8d5af -0, 132086, 132086, 512, 1024, 0xeecbdc04 +0, 128507, 128507, 512, 1024, 0xcaf3deb5 +0, 129019, 129019, 512, 1024, 0x487ce92d +0, 129531, 129531, 512, 1024, 0x117feb95 +0, 130040, 130040, 512, 1024, 0x7b63de3d +0, 130558, 130558, 512, 1024, 0xa529d8e1 +0, 131070, 131070, 512, 1024, 0x56f6da26 +0, 131582, 131582, 512, 1024, 0xffb8d5af +0, 132091, 132091, 512, 1024, 0xeecbdc04 0, 132598, 132598, 512, 1024, 0xfc59d2d2 -0, 133110, 133110, 512, 1024, 0xaf7acef7 -0, 133622, 133622, 512, 1024, 0x3f9bf258 -0, 134134, 134134, 512, 1024, 0xcf54e9d6 -0, 134646, 134646, 512, 1024, 0x680cd0aa -0, 135158, 135158, 512, 1024, 0x3c1bdc1f -0, 135670, 135670, 512, 1024, 0x8c8ffe22 -0, 136182, 136182, 512, 1024, 0xf415d362 -0, 136694, 136694, 512, 1024, 0x8c8cdaa9 -0, 137206, 137206, 512, 1024, 0x9531e9f1 -0, 137718, 137718, 512, 1024, 0x223ce536 -0, 138230, 138230, 512, 1024, 0xdfbce5f9 -0, 138742, 138742, 512, 1024, 0x20b6ed7d -0, 139254, 139254, 512, 1024, 0x1a17e109 -0, 139766, 139766, 512, 1024, 0xc672eaea -0, 140278, 140278, 512, 1024, 0x12a7dc5e -0, 140790, 140790, 512, 1024, 0x4497f342 -0, 141302, 141302, 512, 1024, 0xdfb5db4b -0, 141814, 141814, 512, 1024, 0xde48ef6c -0, 142326, 142326, 512, 1024, 0x1d98e316 -0, 142838, 142838, 512, 1024, 0xbd2ad72f -0, 143350, 143350, 512, 1024, 0xf1aad776 -0, 143862, 143862, 512, 1024, 0x4db3e3c0 -0, 144374, 144374, 512, 1024, 0x832de0a0 -0, 144886, 144886, 512, 1024, 0xc5f0ef25 -0, 145398, 145398, 512, 1024, 0x419bda6e -0, 145910, 145910, 512, 1024, 0x5de7f77e -0, 146422, 146422, 512, 1024, 0x0063ec9a -0, 146934, 146934, 512, 1024, 0x10c3d470 -0, 147446, 147446, 512, 1024, 0xba66d226 -0, 147958, 147958, 512, 1024, 0xea47ded3 -0, 148470, 148470, 512, 1024, 0x6202d67b -0, 148982, 148982, 512, 1024, 0x3f80e7cf -0, 149494, 149494, 512, 1024, 0x4e64eaae -0, 150006, 150006, 512, 1024, 0x2108e83d -0, 150518, 150518, 512, 1024, 0x38c3dec1 -0, 151030, 151030, 512, 1024, 0x46d3f77a -0, 151542, 151542, 512, 1024, 0x4838e787 -0, 152054, 152054, 512, 1024, 0xc71df16d -0, 152566, 152566, 512, 1024, 0xdbe4ebbd -0, 153078, 153078, 512, 1024, 0xa156d07b +0, 133116, 133116, 512, 1024, 0xaf7acef7 +0, 133628, 133628, 512, 1024, 0x3f9bf258 +0, 134140, 134140, 512, 1024, 0xcf54e9d6 +0, 134649, 134649, 512, 1024, 0x680cd0aa +0, 135167, 135167, 512, 1024, 0x3c1bdc1f +0, 135679, 135679, 512, 1024, 0x8c8ffe22 +0, 136191, 136191, 512, 1024, 0xf415d362 +0, 136699, 136699, 512, 1024, 0x8c8cdaa9 +0, 137207, 137207, 512, 1024, 0x9531e9f1 +0, 137724, 137724, 512, 1024, 0x223ce536 +0, 138236, 138236, 512, 1024, 0xdfbce5f9 +0, 138748, 138748, 512, 1024, 0x20b6ed7d +0, 139257, 139257, 512, 1024, 0x1a17e109 +0, 139775, 139775, 512, 1024, 0xc672eaea +0, 140287, 140287, 512, 1024, 0x12a7dc5e +0, 140799, 140799, 512, 1024, 0x4497f342 +0, 141308, 141308, 512, 1024, 0xdfb5db4b +0, 141815, 141815, 512, 1024, 0xde48ef6c +0, 142333, 142333, 512, 1024, 0x1d98e316 +0, 142845, 142845, 512, 1024, 0xbd2ad72f +0, 143357, 143357, 512, 1024, 0xf1aad776 +0, 143866, 143866, 512, 1024, 0x4db3e3c0 +0, 144383, 144383, 512, 1024, 0x832de0a0 +0, 144895, 144895, 512, 1024, 0xc5f0ef25 +0, 145407, 145407, 512, 1024, 0x419bda6e +0, 145916, 145916, 512, 1024, 0x5de7f77e +0, 146424, 146424, 512, 1024, 0x0063ec9a +0, 146941, 146941, 512, 1024, 0x10c3d470 +0, 147453, 147453, 512, 1024, 0xba66d226 +0, 147965, 147965, 512, 1024, 0xea47ded3 +0, 148474, 148474, 512, 1024, 0x6202d67b +0, 148992, 148992, 512, 1024, 0x3f80e7cf +0, 149504, 149504, 512, 1024, 0x4e64eaae +0, 150016, 150016, 512, 1024, 0x2108e83d +0, 150525, 150525, 512, 1024, 0x38c3dec1 +0, 151032, 151032, 512, 1024, 0x46d3f77a +0, 151550, 151550, 512, 1024, 0x4838e787 +0, 152062, 152062, 512, 1024, 0xc71df16d +0, 152574, 152574, 512, 1024, 0xdbe4ebbd +0, 153083, 153083, 512, 1024, 0xa156d07b 0, 153590, 153590, 512, 1024, 0x34eddc80 -0, 154102, 154102, 512, 1024, 0xe840e87c -0, 154614, 154614, 512, 1024, 0x6accf8f5 -0, 155126, 155126, 512, 1024, 0xa1dbebb9 -0, 155638, 155638, 512, 1024, 0x6d07d98c -0, 156150, 156150, 512, 1024, 0x94c7e805 -0, 156662, 156662, 512, 1024, 0x5199e586 -0, 157174, 157174, 512, 1024, 0xe797e1aa -0, 157686, 157686, 512, 1024, 0xff19eda7 +0, 154107, 154107, 512, 1024, 0xe840e87c +0, 154619, 154619, 512, 1024, 0x6accf8f5 +0, 155131, 155131, 512, 1024, 0xa1dbebb9 +0, 155640, 155640, 512, 1024, 0x6d07d98c +0, 156158, 156158, 512, 1024, 0x94c7e805 +0, 156670, 156670, 512, 1024, 0x5199e586 +0, 157182, 157182, 512, 1024, 0xe797e1aa +0, 157691, 157691, 512, 1024, 0xff19eda7 0, 158198, 158198, 512, 1024, 0x9cb9d040 -0, 158710, 158710, 512, 1024, 0xaeedd325 -0, 159222, 159222, 512, 1024, 0xf5ade306 -0, 159734, 159734, 512, 1024, 0x54a5e129 -0, 160246, 160246, 512, 1024, 0x6665ddeb -0, 160758, 160758, 512, 1024, 0x9d18e033 -0, 161270, 161270, 512, 1024, 0x7f23df74 -0, 161782, 161782, 512, 1024, 0x7c34f158 -0, 162294, 162294, 512, 1024, 0x47f6dae2 -0, 162806, 162806, 512, 1024, 0x5ffdd903 -0, 163318, 163318, 512, 1024, 0x8233d108 -0, 163830, 163830, 512, 1024, 0x45c6e20d -0, 164342, 164342, 512, 1024, 0xae11fa6e -0, 164854, 164854, 512, 1024, 0xa30defd2 -0, 165366, 165366, 512, 1024, 0xfc1ecccf -0, 165878, 165878, 512, 1024, 0x920edc94 -0, 166390, 166390, 512, 1024, 0xd7f3dc58 -0, 166902, 166902, 512, 1024, 0x4972d37d -0, 167414, 167414, 512, 1024, 0xfefef358 -0, 167926, 167926, 512, 1024, 0x3648e473 -0, 168438, 168438, 512, 1024, 0x58dee6c3 -0, 168950, 168950, 512, 1024, 0x9cc6df27 -0, 169462, 169462, 512, 1024, 0x6adfe99c -0, 169974, 169974, 512, 1024, 0x6a56e11f -0, 170486, 170486, 512, 1024, 0x4860edf1 -0, 170998, 170998, 512, 1024, 0x9132f10a -0, 171510, 171510, 512, 1024, 0x3e09d209 -0, 172022, 172022, 512, 1024, 0x4b6bf4d8 -0, 172534, 172534, 512, 1024, 0x0cd5e838 -0, 173046, 173046, 512, 1024, 0x080be078 -0, 173558, 173558, 512, 1024, 0xfdb0e31c -0, 174070, 174070, 512, 1024, 0xced5e7bd -0, 174582, 174582, 512, 1024, 0x65b3e435 -0, 175094, 175094, 512, 1024, 0x5b5bfe2e -0, 175606, 175606, 512, 1024, 0xa8bde3cb -0, 176118, 176118, 512, 1024, 0xfd0fdefa -0, 176630, 176630, 512, 1024, 0xbec4ef95 -0, 177142, 177142, 512, 1024, 0x683ad8dd -0, 177654, 177654, 512, 1024, 0x8eefeb77 -0, 178166, 178166, 512, 1024, 0x84fc5878 -0, 178678, 178678, 512, 1024, 0x9a0ded60 +0, 158716, 158716, 512, 1024, 0xaeedd325 +0, 159228, 159228, 512, 1024, 0xf5ade306 +0, 159740, 159740, 512, 1024, 0x54a5e129 +0, 160249, 160249, 512, 1024, 0x6665ddeb +0, 160767, 160767, 512, 1024, 0x9d18e033 +0, 161279, 161279, 512, 1024, 0x7f23df74 +0, 161791, 161791, 512, 1024, 0x7c34f158 +0, 162300, 162300, 512, 1024, 0x47f6dae2 +0, 162807, 162807, 512, 1024, 0x5ffdd903 +0, 163324, 163324, 512, 1024, 0x8233d108 +0, 163836, 163836, 512, 1024, 0x45c6e20d +0, 164348, 164348, 512, 1024, 0xae11fa6e +0, 164857, 164857, 512, 1024, 0xa30defd2 +0, 165375, 165375, 512, 1024, 0xfc1ecccf +0, 165887, 165887, 512, 1024, 0x920edc94 +0, 166399, 166399, 512, 1024, 0xd7f3dc58 +0, 166908, 166908, 512, 1024, 0x4972d37d +0, 167415, 167415, 512, 1024, 0xfefef358 +0, 167933, 167933, 512, 1024, 0x3648e473 +0, 168445, 168445, 512, 1024, 0x58dee6c3 +0, 168957, 168957, 512, 1024, 0x9cc6df27 +0, 169466, 169466, 512, 1024, 0x6adfe99c +0, 169983, 169983, 512, 1024, 0x6a56e11f +0, 170495, 170495, 512, 1024, 0x4860edf1 +0, 171007, 171007, 512, 1024, 0x9132f10a +0, 171516, 171516, 512, 1024, 0x3e09d209 +0, 172024, 172024, 512, 1024, 0x4b6bf4d8 +0, 172541, 172541, 512, 1024, 0x0cd5e838 +0, 173053, 173053, 512, 1024, 0x080be078 +0, 173565, 173565, 512, 1024, 0xfdb0e31c +0, 174074, 174074, 512, 1024, 0xced5e7bd +0, 174592, 174592, 512, 1024, 0x65b3e435 +0, 175104, 175104, 512, 1024, 0x5b5bfe2e +0, 175616, 175616, 512, 1024, 0xa8bde3cb +0, 176125, 176125, 512, 1024, 0xfd0fdefa +0, 176632, 176632, 512, 1024, 0xbec4ef95 +0, 177150, 177150, 512, 1024, 0x683ad8dd +0, 177662, 177662, 512, 1024, 0x8eefeb77 +0, 178174, 178174, 512, 1024, 0x84fc5878 +0, 178683, 178683, 512, 1024, 0x9a0ded60 diff --git a/tests/ref/fate/dcinema-encode b/tests/ref/fate/dcinema-encode index 03e6e6ef6c..cc53488be1 100644 --- a/tests/ref/fate/dcinema-encode +++ b/tests/ref/fate/dcinema-encode @@ -10,21 +10,21 @@ #stream#, dts, pts, duration, size, hash 0, 0, 0, 341, 4092, 697cddfcd0e21f24782af0705b7048f3 0, 341, 341, 341, 4092, a057b18cd493923fed33c18578f61e0b -0, 682, 682, 341, 4092, f4eacfd888566040067b8e5ce7d276c6 -0, 1023, 1023, 341, 4092, 4de78d332ce2047014880a110c160dc2 +0, 683, 683, 341, 4092, f4eacfd888566040067b8e5ce7d276c6 +0, 1024, 1024, 341, 4092, 4de78d332ce2047014880a110c160dc2 0, 1364, 1364, 341, 4092, 138ee3fc206538feca6de3d6d62d08eb -0, 1705, 1705, 341, 4092, 187a2f2998aa1c0ba0130c57dd1d6c86 -0, 2046, 2046, 341, 4092, 54e6c3db8a5f8c09b47f025659a36b17 +0, 1706, 1706, 341, 4092, 187a2f2998aa1c0ba0130c57dd1d6c86 +0, 2047, 2047, 341, 4092, 54e6c3db8a5f8c09b47f025659a36b17 0, 2387, 2387, 341, 4092, 8abfdf44a24c158429c71e01cee31e20 -0, 2728, 2728, 341, 4092, bd08f5018edc5dc4520739e913ed89a3 -0, 3069, 3069, 341, 4092, 9f60ba4275646344e4a9b3c647efffe9 -0, 3410, 3410, 341, 4092, 00cefc1f27230cdd06ecd43132e16327 +0, 2729, 2729, 341, 4092, bd08f5018edc5dc4520739e913ed89a3 +0, 3070, 3070, 341, 4092, 9f60ba4275646344e4a9b3c647efffe9 +0, 3411, 3411, 341, 4092, 00cefc1f27230cdd06ecd43132e16327 0, 3751, 3751, 341, 4092, d4d13047cd639ed722a4ae1bc1f06991 -0, 4092, 4092, 341, 4092, 16b227e4f968c11cba279506f00d5172 -0, 4433, 4433, 341, 4092, 70f4046f709fdd4d80e2f2ffc862f21a +0, 4093, 4093, 341, 4092, 16b227e4f968c11cba279506f00d5172 +0, 4434, 4434, 341, 4092, 70f4046f709fdd4d80e2f2ffc862f21a 0, 4774, 4774, 341, 4092, adbef4b4ef728f0c2a31b4b0baba50a0 -0, 5115, 5115, 341, 4092, fe009b6cc96b9d1098dcc5fba0e6b3fa -0, 5456, 5456, 341, 4092, 4462b2f1654c9b31fdd7ab04ffb84192 +0, 5116, 5116, 341, 4092, fe009b6cc96b9d1098dcc5fba0e6b3fa +0, 5457, 5457, 341, 4092, 4462b2f1654c9b31fdd7ab04ffb84192 0, 5797, 5797, 341, 4092, 2e96ba3bd13de03f9cfdc2b8c3ea0620 -0, 6138, 6138, 341, 4092, 395c920f10cce6670029a98095eba027 -0, 6479, 6479, 341, 4092, 28d4c2f6364f31cb61f4aa144badc734 +0, 6139, 6139, 341, 4092, 395c920f10cce6670029a98095eba027 +0, 6480, 6480, 341, 4092, 28d4c2f6364f31cb61f4aa144badc734 diff --git a/tests/ref/lavf/smjpeg b/tests/ref/lavf/smjpeg index 537c0847cb..94172a6b1e 100644 --- a/tests/ref/lavf/smjpeg +++ b/tests/ref/lavf/smjpeg @@ -1,3 +1,3 @@ 3fe90213ac4f5275eb85ad0a4e4bdb44 *tests/data/lavf/lavf.smjpeg 728642 tests/data/lavf/lavf.smjpeg -tests/data/lavf/lavf.smjpeg CRC=0x54bf6147 +tests/data/lavf/lavf.smjpeg CRC=0x75066147 From a90e41c59028ae4d83df81ebf05261aae15194b5 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Mon, 18 Oct 2021 14:31:36 -0700 Subject: [PATCH 191/894] doc/examples/metadata: Constify values from av_dict_get() Treat values returned from av_dict_get() as const, since they are internal to AVDictionary. Signed-off-by: Chad Fraleigh Signed-off-by: Andreas Rheinhardt --- doc/examples/metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/examples/metadata.c b/doc/examples/metadata.c index b6cfa6bd36..7c44009a24 100644 --- a/doc/examples/metadata.c +++ b/doc/examples/metadata.c @@ -34,7 +34,7 @@ int main (int argc, char **argv) { AVFormatContext *fmt_ctx = NULL; - AVDictionaryEntry *tag = NULL; + const AVDictionaryEntry *tag = NULL; int ret; if (argc != 2) { From a185b526a9267923fb4e67f5fded90e359aea169 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Mon, 18 Oct 2021 15:27:01 -0700 Subject: [PATCH 192/894] fftools: Constify values from av_dict_get() Treat values returned from av_dict_get() as const, since they are internal to AVDictionary. Signed-off-by: Chad Fraleigh Signed-off-by: Andreas Rheinhardt --- fftools/cmdutils.c | 2 +- fftools/ffmpeg.c | 6 +++--- fftools/ffmpeg_filter.c | 6 +++--- fftools/ffmpeg_opt.c | 8 ++++---- fftools/ffplay.c | 8 ++++---- fftools/ffprobe.c | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 594eeef379..45322f8c71 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2121,7 +2121,7 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, AVFormatContext *s, AVStream *st, const AVCodec *codec) { AVDictionary *ret = NULL; - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM : AV_OPT_FLAG_DECODING_PARAM; char prefix = 0; diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b1d2c69fa7..7dfcfc13f5 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -677,7 +677,7 @@ static void ffmpeg_cleanup(int ret) void remove_avoptions(AVDictionary **a, AVDictionary *b) { - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; while ((t = av_dict_get(b, "", t, AV_DICT_IGNORE_SUFFIX))) { av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE); @@ -686,7 +686,7 @@ void remove_avoptions(AVDictionary **a, AVDictionary *b) void assert_avoptions(AVDictionary *m) { - AVDictionaryEntry *t; + const AVDictionaryEntry *t; if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key); exit_program(1); @@ -3228,7 +3228,7 @@ static int init_output_stream_streamcopy(OutputStream *ost) static void set_encoder_id(OutputFile *of, OutputStream *ost) { - AVDictionaryEntry *e; + const AVDictionaryEntry *e; uint8_t *encoder_string; int encoder_string_len; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index b798459946..c70903295f 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -86,7 +86,7 @@ static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx static char *choose_pix_fmts(OutputFilter *ofilter) { OutputStream *ost = ofilter->ost; - AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); + const AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); if (strict_dict) // used by choose_pixel_fmt() and below av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); @@ -437,7 +437,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, if ((ofilter->width || ofilter->height) && ofilter->ost->autoscale) { char args[255]; AVFilterContext *filter; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "%d:%d", ofilter->width, ofilter->height); @@ -994,7 +994,7 @@ int configure_filtergraph(FilterGraph *fg) if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; if (filter_nbthreads) { ret = av_opt_set(fg->graph, "threads", filter_nbthreads, 0); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index ce8bae0775..b423d0e59c 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -249,7 +249,7 @@ static int show_hwaccels(void *optctx, const char *opt, const char *arg) /* return a copy of the input with the stream specifiers removed from the keys */ static AVDictionary *strip_specifiers(AVDictionary *dict) { - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; AVDictionary *ret = NULL; while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))) { @@ -1074,7 +1074,7 @@ static void dump_attachment(AVStream *st, const char *filename) { int ret; AVIOContext *out = NULL; - AVDictionaryEntry *e; + const AVDictionaryEntry *e; if (!st->codecpar->extradata_size) { av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n", @@ -1110,7 +1110,7 @@ static int open_input_file(OptionsContext *o, const char *filename) int err, i, ret; int64_t timestamp; AVDictionary *unused_opts = NULL; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; char * video_codec_name = NULL; char * audio_codec_name = NULL; char *subtitle_codec_name = NULL; @@ -2279,7 +2279,7 @@ static int open_output_file(OptionsContext *o, const char *filename) OutputStream *ost; InputStream *ist; AVDictionary *unused_opts = NULL; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { o->stop_time = INT64_MAX; diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 4b2e69e613..e7b20be76b 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -1856,7 +1856,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL; AVCodecParameters *codecpar = is->video_st->codecpar; AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL); - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; int nb_pix_fmts = 0; int i, j; @@ -1960,7 +1960,7 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for int channels[2] = { 0, -1 }; AVFilterContext *filt_asrc = NULL, *filt_asink = NULL; char aresample_swr_opts[512] = ""; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; char asrc_args[256]; int ret; @@ -2575,7 +2575,7 @@ static int stream_component_open(VideoState *is, int stream_index) const AVCodec *codec; const char *forced_codec_name = NULL; AVDictionary *opts = NULL; - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; int sample_rate, nb_channels; int64_t channel_layout; int ret = 0; @@ -2760,7 +2760,7 @@ static int read_thread(void *arg) AVPacket *pkt = NULL; int64_t stream_start_time; int pkt_in_play_range = 0; - AVDictionaryEntry *t; + const AVDictionaryEntry *t; SDL_mutex *wait_mutex = SDL_CreateMutex(); int scan_all_pmts_set = 0; int64_t pkt_ts; diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 90e895bbf9..169c26b65c 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -580,7 +580,7 @@ static int writer_open(WriterContext **wctx, const Writer *writer, const char *a /* convert options to dictionary */ if (args) { AVDictionary *opts = NULL; - AVDictionaryEntry *opt = NULL; + const AVDictionaryEntry *opt = NULL; if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) { av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args); @@ -1836,7 +1836,7 @@ static void writer_register_all(void) static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id) { - AVDictionaryEntry *tag = NULL; + const AVDictionaryEntry *tag = NULL; int ret = 0; if (!tags) @@ -2364,7 +2364,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_int("max_content", metadata->MaxCLL); print_int("max_average", metadata->MaxFALL); } else if (sd->type == AV_FRAME_DATA_ICC_PROFILE) { - AVDictionaryEntry *tag = av_dict_get(sd->metadata, "name", NULL, AV_DICT_MATCH_CASE); + const AVDictionaryEntry *tag = av_dict_get(sd->metadata, "name", NULL, AV_DICT_MATCH_CASE); if (tag) print_str(tag->key, tag->value); print_int("size", sd->size); @@ -2957,7 +2957,7 @@ static int open_input_file(InputFile *ifile, const char *filename, { int err, i; AVFormatContext *fmt_ctx = NULL; - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; int scan_all_pmts_set = 0; fmt_ctx = avformat_alloc_context(); From bd5ec3601f03c8fb5514673e862223defa6f7673 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Sep 2021 12:27:16 +0200 Subject: [PATCH 193/894] avutil/hwcontext_qsv: Fix leak of AVBuffer and AVBufferRef This av_buffer_create() does nothing but leak an AVBuffer and an AVBufferRef (except on allocation error). Fixes Coverity issue 1491393. Signed-off-by: Andreas Rheinhardt --- libavutil/hwcontext_qsv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index c18747f7eb..4ed50a31a0 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -235,8 +235,6 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size) if (s->nb_surfaces_used < hwctx->nb_surfaces) { s->nb_surfaces_used++; - av_buffer_create((uint8_t*)(s->handle_pairs_internal + s->nb_surfaces_used - 1), - sizeof(*s->handle_pairs_internal), qsv_pool_release_dummy, NULL, 0); return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1), sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0); } From 9181b9ec7c7e13a4f45847f2535ada67024ca16c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Sep 2021 12:31:50 +0200 Subject: [PATCH 194/894] avutil/hwcontext_qsv: Remove redundant check It has already been checked immediately before that said AVDictionaryEntry exists; checking again is redundant. Furthermore, av_hwdevice_find_type_by_name() requires its argument to be non-NULL, so adding a codepath that automatically calls it with that parameter is nonsense. The same goes for the argument corresponding to %s. Fixes Coverity issue 1491394. Signed-off-by: Andreas Rheinhardt --- libavutil/hwcontext_qsv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 4ed50a31a0..268be9f8a1 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1463,10 +1463,10 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, e = av_dict_get(opts, "child_device_type", NULL, 0); if (e) { - child_device_type = av_hwdevice_find_type_by_name(e ? e->value : NULL); + child_device_type = av_hwdevice_find_type_by_name(e->value); if (child_device_type == AV_HWDEVICE_TYPE_NONE) { av_log(ctx, AV_LOG_ERROR, "Unknown child device type " - "\"%s\".\n", e ? e->value : NULL); + "\"%s\".\n", e->value); return AVERROR(EINVAL); } } else if (CONFIG_VAAPI) { From daef8cbff70389e0a5c8b5bd7f05536a4adc2933 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Sun, 14 Nov 2021 20:15:56 +0000 Subject: [PATCH 195/894] avutil/frame: Document the possibility of negative line sizes Signed-off-by: softworkz Signed-off-by: Marton Balint --- libavutil/frame.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libavutil/frame.h b/libavutil/frame.h index 14097f0620..753234792e 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -311,7 +311,8 @@ typedef struct AVFrame { #define AV_NUM_DATA_POINTERS 8 /** * pointer to the picture/channel planes. - * This might be different from the first allocated byte + * This might be different from the first allocated byte. For video, + * it could even point to the end of the image data. * * Some decoders access areas outside 0,0 - width,height, please * see avcodec_align_dimensions2(). Some filters and swscale can read @@ -320,12 +321,20 @@ typedef struct AVFrame { * * NOTE: Except for hwaccel formats, pointers not needed by the format * MUST be set to NULL. + * + * @attention In case of video, the data[] pointers can point to the + * end of image data in order to reverse line order, when used in + * combination with negative values in the linesize[] array. */ uint8_t *data[AV_NUM_DATA_POINTERS]; /** - * For video, size in bytes of each picture line. - * For audio, size in bytes of each plane. + * For video, a positive or negative value, which is typically indicating + * the size in bytes of each picture line, but it can also be: + * - the negative byte size of lines for vertical flipping + * (with data[n] pointing to the end of the data + * - a positive or negative multiple of the byte size as for accessing + * even and odd fields of a frame (possibly flipped) * * For audio, only linesize[0] may be set. For planar audio, each channel * plane must be the same size. @@ -337,6 +346,9 @@ typedef struct AVFrame { * * @note The linesize may be larger than the size of usable data -- there * may be extra padding present for performance reasons. + * + * @attention In case of video, line size values can be negative to achieve + * a vertically inverted iteration over image lines. */ int linesize[AV_NUM_DATA_POINTERS]; From 9b15f43cf8c7976fba115da686a990377f7b5ab9 Mon Sep 17 00:00:00 2001 From: Gijs Peskens Date: Wed, 17 Nov 2021 15:19:28 +0100 Subject: [PATCH 196/894] avformat/librist: correctly initialize logging_settings Correct solution as suggested by Marton Balint on ffmpeg-devel Signed-off-by: Marton Balint --- libavformat/librist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/librist.c b/libavformat/librist.c index 6eae90cc2f..378b635ea7 100644 --- a/libavformat/librist.c +++ b/libavformat/librist.c @@ -130,6 +130,7 @@ static int librist_open(URLContext *h, const char *uri, int flags) if ((flags & AVIO_FLAG_READ_WRITE) == AVIO_FLAG_READ_WRITE) return AVERROR(EINVAL); + s->logging_settings = (struct rist_logging_settings)LOGGING_SETTINGS_INITIALIZER; ret = rist_logging_set(&logging_settings, s->log_level, log_cb, h, NULL, NULL); if (ret < 0) return risterr2ret(ret); From 2f472d5d653ae3b8e7d99e2449ae8fb71b502e6d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 Nov 2021 21:33:46 +0100 Subject: [PATCH 197/894] avfilter/af_drmeter: refactor number of bins out --- libavfilter/af_drmeter.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index a4f35b130a..1ff769a29f 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -26,13 +26,15 @@ #include "avfilter.h" #include "internal.h" +#define BINS 10000 + typedef struct ChannelStats { uint64_t nb_samples; uint64_t blknum; float peak; float sum; - uint32_t peaks[10001]; - uint32_t rms[10001]; + uint32_t peaks[BINS+1]; + uint32_t rms[BINS+1]; } ChannelStats; typedef struct DRMeterContext { @@ -73,8 +75,8 @@ static void finish_block(ChannelStats *p) rms = sqrt(2 * p->sum / p->nb_samples); peak = p->peak; - rms_bin = av_clip(rms * 10000, 0, 10000); - peak_bin = av_clip(peak * 10000, 0, 10000); + rms_bin = av_clip(rms * BINS, 0, BINS); + peak_bin = av_clip(peak * BINS, 0, BINS); p->rms[rms_bin]++; p->peaks[peak_bin]++; @@ -144,29 +146,29 @@ static void print_stats(AVFilterContext *ctx) finish_block(p); - for (i = 0; i <= 10000; i++) { - if (p->peaks[10000 - i]) { + for (i = 0; i <= BINS; i++) { + if (p->peaks[BINS - i]) { if (first) break; first = 1; } } - secondpeak = (10000 - i) / 10000.; + secondpeak = (BINS - i) / (double)BINS; - for (i = 10000, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { + for (i = BINS, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { if (p->rms[i]) { - rmssum += SQR(i / 10000.) * p->rms[i]; + rmssum += SQR(i / (double)BINS) * p->rms[i]; j += p->rms[i]; } } chdr = 20 * log10(secondpeak / sqrt(rmssum / (0.2 * p->blknum))); dr += chdr; - av_log(ctx, AV_LOG_INFO, "Channel %d: DR: %.1f\n", ch + 1, chdr); + av_log(ctx, AV_LOG_INFO, "Channel %d: DR: %g\n", ch + 1, chdr); } - av_log(ctx, AV_LOG_INFO, "Overall DR: %.1f\n", dr / s->nb_channels); + av_log(ctx, AV_LOG_INFO, "Overall DR: %g\n", dr / s->nb_channels); } static av_cold void uninit(AVFilterContext *ctx) From 8c150d3d9794c29a54bbdf2f2a88066277c7197e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 Nov 2021 22:14:11 +0100 Subject: [PATCH 198/894] avfilter/af_drmeter: improve measurement precision --- libavfilter/af_drmeter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index 1ff769a29f..6e0d80a3f1 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -26,7 +26,7 @@ #include "avfilter.h" #include "internal.h" -#define BINS 10000 +#define BINS 32768 typedef struct ChannelStats { uint64_t nb_samples; @@ -75,8 +75,8 @@ static void finish_block(ChannelStats *p) rms = sqrt(2 * p->sum / p->nb_samples); peak = p->peak; - rms_bin = av_clip(rms * BINS, 0, BINS); - peak_bin = av_clip(peak * BINS, 0, BINS); + rms_bin = av_clip(lrintf(rms * BINS), 0, BINS); + peak_bin = av_clip(lrintf(peak * BINS), 0, BINS); p->rms[rms_bin]++; p->peaks[peak_bin]++; @@ -158,7 +158,7 @@ static void print_stats(AVFilterContext *ctx) for (i = BINS, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { if (p->rms[i]) { - rmssum += SQR(i / (double)BINS) * p->rms[i]; + rmssum += SQR(i / (double)BINS); j += p->rms[i]; } } From d1133e8c44f457f0698c48f2efcedbd8626b3cee Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 19 Nov 2021 07:46:15 +0100 Subject: [PATCH 199/894] lavu/vulkan: move common Vulkan code from libavfilter to libavutil --- configure | 2 +- libavfilter/glslang.c | 239 +-- libavfilter/vf_avgblur_vulkan.c | 74 +- libavfilter/vf_chromaber_vulkan.c | 56 +- libavfilter/vf_gblur_vulkan.c | 88 +- libavfilter/vf_libplacebo.c | 2 +- libavfilter/vf_overlay_vulkan.c | 71 +- libavfilter/vf_scale_vulkan.c | 73 +- libavfilter/vulkan.c | 1391 +--------------- libavfilter/vulkan.h | 380 +---- libavutil/hwcontext_vulkan.c | 10 +- libavutil/vulkan.c | 1392 +++++++++++++++++ libavutil/vulkan.h | 413 +++++ libavutil/vulkan_glslang.c | 256 +++ .../glslang.h => libavutil/vulkan_glslang.h | 8 +- 15 files changed, 2258 insertions(+), 2197 deletions(-) create mode 100644 libavutil/vulkan.c create mode 100644 libavutil/vulkan.h create mode 100644 libavutil/vulkan_glslang.c rename libavfilter/glslang.h => libavutil/vulkan_glslang.h (87%) diff --git a/configure b/configure index 1b47f6512d..79252ac223 100755 --- a/configure +++ b/configure @@ -3620,7 +3620,7 @@ interlace_filter_deps="gpl" kerndeint_filter_deps="gpl" ladspa_filter_deps="ladspa libdl" lensfun_filter_deps="liblensfun version3" -libplacebo_filter_deps="libplacebo vulkan libglslang" +libplacebo_filter_deps="libplacebo vulkan" lv2_filter_deps="lv2" mcdeint_filter_deps="avcodec gpl" metadata_filter_deps="avformat" diff --git a/libavfilter/glslang.c b/libavfilter/glslang.c index e5a8d4dc2a..9aa41567a3 100644 --- a/libavfilter/glslang.c +++ b/libavfilter/glslang.c @@ -16,241 +16,4 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - -#include -#include - -#include "libavutil/mem.h" -#include "libavutil/avassert.h" - -#include "glslang.h" - -static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; -static int glslang_refcount = 0; - -static const glslang_resource_t glslc_resource_limits = { - .max_lights = 32, - .max_clip_planes = 6, - .max_texture_units = 32, - .max_texture_coords = 32, - .max_vertex_attribs = 64, - .max_vertex_uniform_components = 4096, - .max_varying_floats = 64, - .max_vertex_texture_image_units = 32, - .max_combined_texture_image_units = 80, - .max_texture_image_units = 32, - .max_fragment_uniform_components = 4096, - .max_draw_buffers = 32, - .max_vertex_uniform_vectors = 128, - .max_varying_vectors = 8, - .max_fragment_uniform_vectors = 16, - .max_vertex_output_vectors = 16, - .max_fragment_input_vectors = 15, - .min_program_texel_offset = -8, - .max_program_texel_offset = 7, - .max_clip_distances = 8, - .max_compute_work_group_count_x = 65535, - .max_compute_work_group_count_y = 65535, - .max_compute_work_group_count_z = 65535, - .max_compute_work_group_size_x = 1024, - .max_compute_work_group_size_y = 1024, - .max_compute_work_group_size_z = 64, - .max_compute_uniform_components = 1024, - .max_compute_texture_image_units = 16, - .max_compute_image_uniforms = 8, - .max_compute_atomic_counters = 8, - .max_compute_atomic_counter_buffers = 1, - .max_varying_components = 60, - .max_vertex_output_components = 64, - .max_geometry_input_components = 64, - .max_geometry_output_components = 128, - .max_fragment_input_components = 128, - .max_image_units = 8, - .max_combined_image_units_and_fragment_outputs = 8, - .max_combined_shader_output_resources = 8, - .max_image_samples = 0, - .max_vertex_image_uniforms = 0, - .max_tess_control_image_uniforms = 0, - .max_tess_evaluation_image_uniforms = 0, - .max_geometry_image_uniforms = 0, - .max_fragment_image_uniforms = 8, - .max_combined_image_uniforms = 8, - .max_geometry_texture_image_units = 16, - .max_geometry_output_vertices = 256, - .max_geometry_total_output_components = 1024, - .max_geometry_uniform_components = 1024, - .max_geometry_varying_components = 64, - .max_tess_control_input_components = 128, - .max_tess_control_output_components = 128, - .max_tess_control_texture_image_units = 16, - .max_tess_control_uniform_components = 1024, - .max_tess_control_total_output_components = 4096, - .max_tess_evaluation_input_components = 128, - .max_tess_evaluation_output_components = 128, - .max_tess_evaluation_texture_image_units = 16, - .max_tess_evaluation_uniform_components = 1024, - .max_tess_patch_components = 120, - .max_patch_vertices = 32, - .max_tess_gen_level = 64, - .max_viewports = 16, - .max_vertex_atomic_counters = 0, - .max_tess_control_atomic_counters = 0, - .max_tess_evaluation_atomic_counters = 0, - .max_geometry_atomic_counters = 0, - .max_fragment_atomic_counters = 8, - .max_combined_atomic_counters = 8, - .max_atomic_counter_bindings = 1, - .max_vertex_atomic_counter_buffers = 0, - .max_tess_control_atomic_counter_buffers = 0, - .max_tess_evaluation_atomic_counter_buffers = 0, - .max_geometry_atomic_counter_buffers = 0, - .max_fragment_atomic_counter_buffers = 1, - .max_combined_atomic_counter_buffers = 1, - .max_atomic_counter_buffer_size = 16384, - .max_transform_feedback_buffers = 4, - .max_transform_feedback_interleaved_components = 64, - .max_cull_distances = 8, - .max_combined_clip_and_cull_distances = 8, - .max_samples = 4, - .max_mesh_output_vertices_nv = 256, - .max_mesh_output_primitives_nv = 512, - .max_mesh_work_group_size_x_nv = 32, - .max_mesh_work_group_size_y_nv = 1, - .max_mesh_work_group_size_z_nv = 1, - .max_task_work_group_size_x_nv = 32, - .max_task_work_group_size_y_nv = 1, - .max_task_work_group_size_z_nv = 1, - .max_mesh_view_count_nv = 4, - .maxDualSourceDrawBuffersEXT = 1, - - .limits = { - .non_inductive_for_loops = 1, - .while_loops = 1, - .do_while_loops = 1, - .general_uniform_indexing = 1, - .general_attribute_matrix_vector_indexing = 1, - .general_varying_indexing = 1, - .general_sampler_indexing = 1, - .general_variable_indexing = 1, - .general_constant_matrix_vector_indexing = 1, - } -}; - -int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, - uint8_t **data, size_t *size, void **opaque) -{ - const char *messages; - glslang_shader_t *glslc_shader; - glslang_program_t *glslc_program; - - static const glslang_stage_t glslc_stage[] = { - [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_STAGE_VERTEX, - [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT, - [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_STAGE_COMPUTE, - }; - - const glslang_input_t glslc_input = { - .language = GLSLANG_SOURCE_GLSL, - .stage = glslc_stage[shd->shader.stage], - .client = GLSLANG_CLIENT_VULKAN, - /* GLSLANG_TARGET_VULKAN_1_2 before 11.6 resulted in targeting 1.0 */ -#if (((GLSLANG_VERSION_MAJOR) > 11) || ((GLSLANG_VERSION_MAJOR) == 11 && \ - (((GLSLANG_VERSION_MINOR) > 6) || ((GLSLANG_VERSION_MINOR) == 6 && \ - ((GLSLANG_VERSION_PATCH) > 0))))) - .client_version = GLSLANG_TARGET_VULKAN_1_2, - .target_language_version = GLSLANG_TARGET_SPV_1_5, -#else - .client_version = GLSLANG_TARGET_VULKAN_1_1, - .target_language_version = GLSLANG_TARGET_SPV_1_3, -#endif - .target_language = GLSLANG_TARGET_SPV, - .code = shd->src.str, - .default_version = 460, - .default_profile = GLSLANG_NO_PROFILE, - .force_default_version_and_profile = false, - .forward_compatible = false, - .messages = GLSLANG_MSG_DEFAULT_BIT, - .resource = &glslc_resource_limits, - }; - - av_assert0(glslang_refcount); - - if (!(glslc_shader = glslang_shader_create(&glslc_input))) - return AVERROR(ENOMEM); - - if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) { - ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); - av_log(avctx, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n", - glslang_shader_get_info_log(glslc_shader), - glslang_shader_get_info_debug_log(glslc_shader)); - glslang_shader_delete(glslc_shader); - return AVERROR(EINVAL); - } - - if (!glslang_shader_parse(glslc_shader, &glslc_input)) { - ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); - av_log(avctx, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n", - glslang_shader_get_info_log(glslc_shader), - glslang_shader_get_info_debug_log(glslc_shader)); - glslang_shader_delete(glslc_shader); - return AVERROR(EINVAL); - } - - if (!(glslc_program = glslang_program_create())) { - glslang_shader_delete(glslc_shader); - return AVERROR(EINVAL); - } - - glslang_program_add_shader(glslc_program, glslc_shader); - - if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT | - GLSLANG_MSG_VULKAN_RULES_BIT)) { - ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); - av_log(avctx, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n", - glslang_program_get_info_log(glslc_program), - glslang_program_get_info_debug_log(glslc_program)); - glslang_program_delete(glslc_program); - glslang_shader_delete(glslc_shader); - return AVERROR(EINVAL); - } - - glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); - - messages = glslang_program_SPIRV_get_messages(glslc_program); - if (messages) - av_log(avctx, AV_LOG_WARNING, "%s\n", messages); - - glslang_shader_delete(glslc_shader); - - *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int); - *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program); - *opaque = glslc_program; - - return 0; -} - -void ff_vk_glslang_shader_free(void *opaque) -{ - glslang_program_delete(opaque); -} - -int ff_vk_glslang_init(void) -{ - int ret = 0; - - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount++ == 0) - ret = !glslang_initialize_process(); - pthread_mutex_unlock(&glslang_mutex); - - return ret; -} - -void ff_vk_glslang_uninit(void) -{ - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount && (--glslang_refcount == 0)) - glslang_finalize_process(); - pthread_mutex_unlock(&glslang_mutex); -} +#include "libavutil/vulkan_glslang.c" diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 4795e482a9..d37d5a62b1 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -71,8 +71,9 @@ static const char blur_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - FFSPIRVShader *shd; + FFVkSPIRVShader *shd; AvgBlurVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); FFVulkanDescriptorSetBinding desc_i[2] = { @@ -94,9 +95,9 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - desc_i[0].sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); + desc_i[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); if (!desc_i[0].sampler) return AVERROR_EXTERNAL; @@ -104,16 +105,16 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) desc_i[0].updater = s->input_images; desc_i[1].updater = s->tmp_images; - s->pl_hor = ff_vk_create_pipeline(ctx, &s->qf); + s->pl_hor = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl_hor) return AVERROR(ENOMEM); - shd = ff_vk_init_shader(ctx, s->pl_hor, "avgblur_compute_hor", + shd = ff_vk_init_shader(s->pl_hor, "avgblur_compute_hor", VK_SHADER_STAGE_COMPUTE_BIT); - ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, 1, 1 }); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); - RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, desc_i, 2, 0)); + RET(ff_vk_add_descriptor_set(vkctx, s->pl_hor, shd, desc_i, 2, 0)); GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_x - 1); GLSLC(0, #define INC(x) (ivec2(x, 0)) ); @@ -137,26 +138,26 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); - RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl_hor)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl_hor)); } { /* Create shader for the vertical pass */ desc_i[0].updater = s->tmp_images; desc_i[1].updater = s->output_images; - s->pl_ver = ff_vk_create_pipeline(ctx, &s->qf); + s->pl_ver = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl_ver) return AVERROR(ENOMEM); - shd = ff_vk_init_shader(ctx, s->pl_ver, "avgblur_compute_ver", + shd = ff_vk_init_shader(s->pl_ver, "avgblur_compute_ver", VK_SHADER_STAGE_COMPUTE_BIT); - ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ 1, CGS, 1 }); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ 1, CGS, 1 }); - RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, desc_i, 2, 0)); + RET(ff_vk_add_descriptor_set(vkctx, s->pl_ver, shd, desc_i, 2, 0)); GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_y - 1); GLSLC(0, #define INC(x) (ivec2(0, x)) ); @@ -180,14 +181,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); - RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl_ver)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl_ver)); } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -202,29 +203,30 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f int err; VkCommandBuffer cmd_buf; AvgBlurVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkctx.vkfn; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); for (int i = 0; i < planes; i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView, - in->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView, - tmp->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->tmp_images[i].imageView, tmp->img[i], av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], ff_comp_identity_map)); @@ -233,8 +235,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl_hor, 0); - ff_vk_update_descriptor_set(avctx, s->pl_ver, 0); + ff_vk_update_descriptor_set(vkctx, s->pl_hor, 0); + ff_vk_update_descriptor_set(vkctx, s->pl_ver, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar[] = { @@ -293,20 +295,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f out->access[i] = bar[2].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl_hor); vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, s->vkctx.output_height, 1); - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl_ver); vk->CmdDispatch(cmd_buf, s->vkctx.output_width, FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); - ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx,s->exec); if (err) return err; @@ -315,7 +317,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -364,7 +366,7 @@ static void avgblur_vulkan_uninit(AVFilterContext *avctx) { AvgBlurVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 83ab72f716..86a66454a4 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -70,16 +70,17 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) int err; FFVkSampler *sampler; ChromaticAberrationVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); /* Create a sampler */ - sampler = ff_vk_init_sampler(ctx, 0, VK_FILTER_LINEAR); + sampler = ff_vk_init_sampler(vkctx, 0, VK_FILTER_LINEAR); if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx, &s->qf); + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); @@ -110,22 +111,22 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "chromaber_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); + ff_vk_set_compute_shader_sizes(shd, CGROUPS); GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); GLSLC(1, vec2 dist; ); GLSLC(0, }; ); GLSLC(0, ); - ff_vk_add_push_constant(ctx, s->pl, 0, sizeof(s->opts), + ff_vk_add_push_constant(s->pl, 0, sizeof(s->opts), VK_SHADER_STAGE_COMPUTE_BIT); - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ GLSLD( distort_chroma_kernel ); GLSLC(0, void main() ); @@ -152,14 +153,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); } - RET(ff_vk_init_pipeline_layout(ctx, s->pl)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -174,23 +175,24 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) int err = 0; VkCommandBuffer cmd_buf; ChromaticAberrationVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkctx.vkfn; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); for (int i = 0; i < planes; i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView, - in->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], ff_comp_identity_map)); @@ -198,7 +200,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl, 0); + ff_vk_update_descriptor_set(vkctx, s->pl, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar[2] = { @@ -241,19 +243,19 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) out->access[i] = bar[1].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); - ff_vk_update_push_exec(avctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT, + ff_vk_update_push_exec(vkctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(s->opts), &s->opts); vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); - ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx, s->exec); if (err) return err; @@ -262,7 +264,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -302,7 +304,7 @@ static void chromaber_vulkan_uninit(AVFilterContext *avctx) { ChromaticAberrationVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index 16c8bbb189..71d88d22e9 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -127,7 +127,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) int err = 0; char *kernel_def; uint8_t *kernel_mapped; - FFSPIRVShader *shd; + FFVkSPIRVShader *shd; GBlurVulkanContext *s = ctx->priv; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); @@ -160,7 +160,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .buf_content = NULL, }; - image_descs[0].sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); + image_descs[0].sampler = ff_vk_init_sampler(&s->vkctx, 1, VK_FILTER_LINEAR); if (!image_descs[0].sampler) return AVERROR_EXTERNAL; @@ -172,28 +172,28 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) buf_desc.buf_content = kernel_def; - ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + ff_vk_qf_init(&s->vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); { /* Create shader for the horizontal pass */ image_descs[0].updater = s->input_images; image_descs[1].updater = s->tmp_images; buf_desc.updater = &s->params_desc_hor; - s->pl_hor = ff_vk_create_pipeline(ctx, &s->qf); + s->pl_hor = ff_vk_create_pipeline(&s->vkctx, &s->qf); if (!s->pl_hor) { err = AVERROR(ENOMEM); goto fail; } - shd = ff_vk_init_shader(ctx, s->pl_hor, "gblur_compute_hor", image_descs[0].stages); + shd = ff_vk_init_shader(s->pl_hor, "gblur_compute_hor", image_descs[0].stages); if (!shd) { err = AVERROR(ENOMEM); goto fail; } - ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 }); - RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); - RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, &buf_desc, 1, 0)); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 }); + RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, &buf_desc, 1, 0)); GLSLD( gblur_horizontal ); GLSLC(0, void main() ); @@ -214,23 +214,23 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(&s->vkctx, shd, "main")); - RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor)); + RET(ff_vk_init_pipeline_layout(&s->vkctx, s->pl_hor)); + RET(ff_vk_init_compute_pipeline(&s->vkctx, s->pl_hor)); - RET(ff_vk_create_buf(ctx, &s->params_buf_hor, sizeof(float) * s->kernel_size, + RET(ff_vk_create_buf(&s->vkctx, &s->params_buf_hor, sizeof(float) * s->kernel_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - RET(ff_vk_map_buffers(ctx, &s->params_buf_hor, &kernel_mapped, 1, 0)); + RET(ff_vk_map_buffers(&s->vkctx, &s->params_buf_hor, &kernel_mapped, 1, 0)); init_gaussian_kernel((float *)kernel_mapped, s->sigma, s->kernel_size); - RET(ff_vk_unmap_buffers(ctx, &s->params_buf_hor, 1, 1)); + RET(ff_vk_unmap_buffers(&s->vkctx, &s->params_buf_hor, 1, 1)); s->params_desc_hor.buffer = s->params_buf_hor.buf; s->params_desc_hor.range = VK_WHOLE_SIZE; - ff_vk_update_descriptor_set(ctx, s->pl_hor, 1); + ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 1); } { /* Create shader for the vertical pass */ @@ -238,21 +238,21 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) image_descs[1].updater = s->output_images; buf_desc.updater = &s->params_desc_ver; - s->pl_ver = ff_vk_create_pipeline(ctx, &s->qf); + s->pl_ver = ff_vk_create_pipeline(&s->vkctx, &s->qf); if (!s->pl_ver) { err = AVERROR(ENOMEM); goto fail; } - shd = ff_vk_init_shader(ctx, s->pl_ver, "gblur_compute_ver", image_descs[0].stages); + shd = ff_vk_init_shader(s->pl_ver, "gblur_compute_ver", image_descs[0].stages); if (!shd) { err = AVERROR(ENOMEM); goto fail; } - ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 }); - RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); - RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, &buf_desc, 1, 0)); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 }); + RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, &buf_desc, 1, 0)); GLSLD( gblur_vertical ); GLSLC(0, void main() ); @@ -273,26 +273,26 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(&s->vkctx, shd, "main")); - RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver)); + RET(ff_vk_init_pipeline_layout(&s->vkctx, s->pl_ver)); + RET(ff_vk_init_compute_pipeline(&s->vkctx, s->pl_ver)); - RET(ff_vk_create_buf(ctx, &s->params_buf_ver, sizeof(float) * s->kernel_size, + RET(ff_vk_create_buf(&s->vkctx, &s->params_buf_ver, sizeof(float) * s->kernel_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - RET(ff_vk_map_buffers(ctx, &s->params_buf_ver, &kernel_mapped, 1, 0)); + RET(ff_vk_map_buffers(&s->vkctx, &s->params_buf_ver, &kernel_mapped, 1, 0)); init_gaussian_kernel((float *)kernel_mapped, s->sigmaV, s->kernel_size); - RET(ff_vk_unmap_buffers(ctx, &s->params_buf_ver, 1, 1)); + RET(ff_vk_unmap_buffers(&s->vkctx, &s->params_buf_ver, 1, 1)); s->params_desc_ver.buffer = s->params_buf_ver.buf; s->params_desc_ver.range = VK_WHOLE_SIZE; - ff_vk_update_descriptor_set(ctx, s->pl_ver, 1); + ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 1); } - RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); + RET(ff_vk_create_exec_ctx(&s->vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -307,9 +307,9 @@ static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx) av_frame_free(&s->tmpframe); - ff_vk_filter_uninit(avctx); - ff_vk_free_buf(avctx, &s->params_buf_hor); - ff_vk_free_buf(avctx, &s->params_buf_ver); + ff_vk_free_buf(&s->vkctx, &s->params_buf_hor); + ff_vk_free_buf(&s->vkctx, &s->params_buf_ver); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } @@ -329,23 +329,23 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + ff_vk_start_exec_recording(&s->vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); for (int i = 0; i < planes; i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView, + RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->input_images[i].imageView, in->img[i], input_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView, + RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->tmp_images[i].imageView, tmp->img[i], output_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, + RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->output_images[i].imageView, out->img[i], output_formats[i], ff_comp_identity_map)); @@ -355,8 +355,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl_hor, 0); - ff_vk_update_descriptor_set(avctx, s->pl_ver, 0); + ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 0); + ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier barriers[] = { @@ -415,20 +415,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in out->access[i] = barriers[2].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor); + ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_hor); vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver); + ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_ver); vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); - ff_vk_add_exec_dep(avctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(&s->vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(&s->vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(&s->vkctx, s->exec); if (err) return err; @@ -436,7 +436,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in return 0; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index ede6888bd3..fe301db417 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -270,7 +270,7 @@ static void libplacebo_uninit(AVFilterContext *avctx) pl_renderer_destroy(&s->renderer); pl_vulkan_destroy(&s->vulkan); pl_log_destroy(&s->log); - ff_vk_filter_uninit(avctx); + ff_vk_uninit(&s->vkctx); s->initialized = 0; s->gpu = NULL; } diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index b902ad83f5..ab97cf2c17 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -82,15 +82,16 @@ static av_cold int init_filter(AVFilterContext *ctx) int err; FFVkSampler *sampler; OverlayVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_NEAREST); + sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_NEAREST); if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx, &s->qf); + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); @@ -138,15 +139,15 @@ static av_cold int init_filter(AVFilterContext *ctx) .buf_content = "ivec2 o_offset[3], o_size[3];", }; - FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "overlay_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); + ff_vk_set_compute_shader_sizes(shd, CGROUPS); - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 3, 0)); /* set 0 */ - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 3, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( overlay_noalpha ); GLSLD( overlay_alpha ); @@ -162,11 +163,11 @@ static av_cold int init_filter(AVFilterContext *ctx) GLSLC(1, } ); GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); } - RET(ff_vk_init_pipeline_layout(ctx, s->pl)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); { /* Create and update buffer */ const AVPixFmtDescriptor *desc; @@ -179,14 +180,14 @@ static av_cold int init_filter(AVFilterContext *ctx) int32_t o_size[2*3]; } *par; - err = ff_vk_create_buf(ctx, &s->params_buf, + err = ff_vk_create_buf(vkctx, &s->params_buf, sizeof(*par), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); if (err) return err; - err = ff_vk_map_buffers(ctx, &s->params_buf, (uint8_t **)&par, 1, 0); + err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0); if (err) return err; @@ -206,18 +207,18 @@ static av_cold int init_filter(AVFilterContext *ctx) par->o_size[4] = par->o_size[0] >> desc->log2_chroma_w; par->o_size[5] = par->o_size[1] >> desc->log2_chroma_h; - err = ff_vk_unmap_buffers(ctx, &s->params_buf, 1, 1); + err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1); if (err) return err; s->params_desc.buffer = s->params_buf.buf; s->params_desc.range = VK_WHOLE_SIZE; - ff_vk_update_descriptor_set(ctx, s->pl, 1); + ff_vk_update_descriptor_set(vkctx, s->pl, 1); } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -233,7 +234,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, int err; VkCommandBuffer cmd_buf; OverlayVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkctx.vkfn; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); AVVkFrame *out = (AVVkFrame *)out_f->data[0]; @@ -244,22 +246,22 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVHWFramesContext *overlay_fc = (AVHWFramesContext*)overlay_f->hw_frames_ctx->data; /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); for (int i = 0; i < planes; i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->main_images[i].imageView, - main->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->main_images[i].imageView, main->img[i], av_vkfmt_from_pixfmt(main_fc->sw_format)[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->overlay_images[i].imageView, - overlay->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->overlay_images[i].imageView, overlay->img[i], av_vkfmt_from_pixfmt(overlay_fc->sw_format)[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], ff_comp_identity_map)); @@ -268,7 +270,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl, 0); + ff_vk_update_descriptor_set(vkctx, s->pl, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar[3] = { @@ -327,17 +329,17 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, out->access[i] = bar[2].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); - ff_vk_add_exec_dep(avctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx, s->exec); if (err) return err; @@ -346,7 +348,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -438,11 +440,10 @@ static void overlay_vulkan_uninit(AVFilterContext *avctx) { OverlayVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); + ff_vk_free_buf(&s->vkctx, &s->params_buf); + ff_vk_uninit(&s->vkctx); ff_framesync_uninit(&s->fs); - ff_vk_free_buf(avctx, &s->params_buf); - s->initialized = 0; } diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 3a2251f8df..c2f6fe85e2 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -111,6 +111,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) FFVkSampler *sampler; VkFilter sampler_mode; ScaleVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; int crop_x = in->crop_left; int crop_y = in->crop_top; @@ -118,7 +119,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) int crop_h = in->height - (in->crop_top + in->crop_bottom); int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format); - ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); switch (s->scaler) { case F_NEAREST: @@ -130,11 +131,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }; /* Create a sampler */ - sampler = ff_vk_init_sampler(ctx, 0, sampler_mode); + sampler = ff_vk_init_sampler(vkctx, 0, sampler_mode); if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx, &s->qf); + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); @@ -171,15 +172,15 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .buf_content = "mat4 yuv_matrix;", }; - FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "scale_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); + ff_vk_set_compute_shader_sizes(shd, CGROUPS); - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( scale_bilinear ); @@ -229,11 +230,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); } - RET(ff_vk_init_pipeline_layout(ctx, s->pl)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); if (s->vkctx.output_format != s->vkctx.input_format) { const struct LumaCoefficients *lcoeffs; @@ -249,14 +250,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) return AVERROR(EINVAL); } - err = ff_vk_create_buf(ctx, &s->params_buf, + err = ff_vk_create_buf(vkctx, &s->params_buf, sizeof(*par), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); if (err) return err; - err = ff_vk_map_buffers(ctx, &s->params_buf, (uint8_t **)&par, 1, 0); + err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0); if (err) return err; @@ -270,18 +271,18 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) par->yuv_matrix[3][3] = 1.0; - err = ff_vk_unmap_buffers(ctx, &s->params_buf, 1, 1); + err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1); if (err) return err; s->params_desc.buffer = s->params_buf.buf; s->params_desc.range = VK_WHOLE_SIZE; - ff_vk_update_descriptor_set(ctx, s->pl, 1); + ff_vk_update_descriptor_set(vkctx, s->pl, 1); } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -296,19 +297,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) int err = 0; VkCommandBuffer cmd_buf; ScaleVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkctx.vkfn; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2]; int barrier_count = 0; /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView, - in->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], ff_comp_identity_map)); @@ -316,15 +318,15 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) } for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.output_format); i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], ff_comp_identity_map)); s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl, 0); + ff_vk_update_descriptor_set(vkctx, s->pl, 0); for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { VkImageMemoryBarrier bar = { @@ -372,16 +374,16 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, barrier_count, barriers); - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); vk->CmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + FFALIGN(vkctx->output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(vkctx->output_height, CGROUPS[1])/CGROUPS[1], 1); - ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx, s->exec); if (err) return err; @@ -390,7 +392,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -436,11 +438,12 @@ static int scale_vulkan_config_output(AVFilterLink *outlink) int err; AVFilterContext *avctx = outlink->src; ScaleVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; AVFilterLink *inlink = outlink->src->inputs[0]; err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, - &s->vkctx.output_width, - &s->vkctx.output_height); + &vkctx->output_width, + &vkctx->output_height); if (err < 0) return err; @@ -481,8 +484,8 @@ static void scale_vulkan_uninit(AVFilterContext *avctx) { ScaleVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); - ff_vk_free_buf(avctx, &s->params_buf); + ff_vk_free_buf(&s->vkctx, &s->params_buf); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index 48f02e4603..e0fcf87f21 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -16,659 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "formats.h" #include "vulkan.h" -#include "glslang.h" - -#include "libavutil/avassert.h" -#include "libavutil/vulkan_loader.h" - -/* Generic macro for creating contexts which need to keep their addresses - * if another context is created. */ -#define FN_CREATING(ctx, type, shortname, array, num) \ -static av_always_inline type *create_ ##shortname(ctx *dctx) \ -{ \ - type **array, *sctx = av_mallocz(sizeof(*sctx)); \ - if (!sctx) \ - return NULL; \ - \ - array = av_realloc_array(dctx->array, sizeof(*dctx->array), dctx->num + 1);\ - if (!array) { \ - av_free(sctx); \ - return NULL; \ - } \ - \ - dctx->array = array; \ - dctx->array[dctx->num++] = sctx; \ - \ - return sctx; \ -} - -const VkComponentMapping ff_comp_identity_map = { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, -}; - -/* Converts return values to strings */ -const char *ff_vk_ret2str(VkResult res) -{ -#define CASE(VAL) case VAL: return #VAL - switch (res) { - CASE(VK_SUCCESS); - CASE(VK_NOT_READY); - CASE(VK_TIMEOUT); - CASE(VK_EVENT_SET); - CASE(VK_EVENT_RESET); - CASE(VK_INCOMPLETE); - CASE(VK_ERROR_OUT_OF_HOST_MEMORY); - CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY); - CASE(VK_ERROR_INITIALIZATION_FAILED); - CASE(VK_ERROR_DEVICE_LOST); - CASE(VK_ERROR_MEMORY_MAP_FAILED); - CASE(VK_ERROR_LAYER_NOT_PRESENT); - CASE(VK_ERROR_EXTENSION_NOT_PRESENT); - CASE(VK_ERROR_FEATURE_NOT_PRESENT); - CASE(VK_ERROR_INCOMPATIBLE_DRIVER); - CASE(VK_ERROR_TOO_MANY_OBJECTS); - CASE(VK_ERROR_FORMAT_NOT_SUPPORTED); - CASE(VK_ERROR_FRAGMENTED_POOL); - CASE(VK_ERROR_SURFACE_LOST_KHR); - CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); - CASE(VK_SUBOPTIMAL_KHR); - CASE(VK_ERROR_OUT_OF_DATE_KHR); - CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR); - CASE(VK_ERROR_VALIDATION_FAILED_EXT); - CASE(VK_ERROR_INVALID_SHADER_NV); - CASE(VK_ERROR_OUT_OF_POOL_MEMORY); - CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE); - CASE(VK_ERROR_NOT_PERMITTED_EXT); - default: return "Unknown error"; - } -#undef CASE -} - -void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int nb_queues) -{ - FFVulkanContext *s = avctx->priv; - - switch (dev_family) { - case VK_QUEUE_GRAPHICS_BIT: - qf->queue_family = s->hwctx->queue_family_index; - qf->actual_queues = s->hwctx->nb_graphics_queues; - break; - case VK_QUEUE_COMPUTE_BIT: - qf->queue_family = s->hwctx->queue_family_comp_index; - qf->actual_queues = s->hwctx->nb_comp_queues; - break; - case VK_QUEUE_TRANSFER_BIT: - qf->queue_family = s->hwctx->queue_family_tx_index; - qf->actual_queues = s->hwctx->nb_tx_queues; - break; - case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: - qf->queue_family = s->hwctx->queue_family_encode_index; - qf->actual_queues = s->hwctx->nb_encode_queues; - break; - case VK_QUEUE_VIDEO_DECODE_BIT_KHR: - qf->queue_family = s->hwctx->queue_family_decode_index; - qf->actual_queues = s->hwctx->nb_decode_queues; - break; - default: - av_assert0(0); /* Should never happen */ - } - - if (!nb_queues) - qf->nb_queues = qf->actual_queues; - else - qf->nb_queues = nb_queues; - - return; -} - -void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) -{ - qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues; -} - -static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, - VkMemoryPropertyFlagBits req_flags, void *alloc_extension, - VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) -{ - VkResult ret; - int index = -1; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - VkMemoryAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = alloc_extension, - }; - - /* Align if we need to */ - if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) - req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment); - - alloc_info.allocationSize = req->size; - - /* The vulkan spec requires memory types to be sorted in the "optimal" - * order, so the first matching type we find will be the best/fastest one */ - for (int i = 0; i < s->mprops.memoryTypeCount; i++) { - /* The memory type must be supported by the requirements (bitfield) */ - if (!(req->memoryTypeBits & (1 << i))) - continue; - - /* The memory type flags must include our properties */ - if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) - continue; - - /* Found a suitable memory type */ - index = i; - break; - } - - if (index < 0) { - av_log(avctx, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", - req_flags); - return AVERROR(EINVAL); - } - - alloc_info.memoryTypeIndex = index; - - ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info, - s->hwctx->alloc, mem); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n", - ff_vk_ret2str(ret)); - return AVERROR(ENOMEM); - } - - *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; - - return 0; -} - -int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, - VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) -{ - int err; - VkResult ret; - int use_ded_mem; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - VkBufferCreateInfo buf_spawn = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = NULL, - .usage = usage, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .size = size, /* Gets FFALIGNED during alloc if host visible - but should be ok */ - }; - - VkBufferMemoryRequirementsInfo2 req_desc = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - }; - VkMemoryDedicatedAllocateInfo ded_alloc = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = NULL, - }; - VkMemoryDedicatedRequirements ded_req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - }; - VkMemoryRequirements2 req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &ded_req, - }; - - ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - req_desc.buffer = buf->buf; - - vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req); - - /* In case the implementation prefers/requires dedicated allocation */ - use_ded_mem = ded_req.prefersDedicatedAllocation | - ded_req.requiresDedicatedAllocation; - if (use_ded_mem) - ded_alloc.buffer = buf->buf; - - err = vk_alloc_mem(avctx, &req.memoryRequirements, flags, - use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, - &buf->flags, &buf->mem); - if (err) - return err; - - ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - return 0; -} - -int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], - int nb_buffers, int invalidate) -{ - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - VkMappedMemoryRange *inval_list = NULL; - int inval_count = 0; - - for (int i = 0; i < nb_buffers; i++) { - ret = vk->MapMemory(s->hwctx->act_dev, buf[i].mem, 0, - VK_WHOLE_SIZE, 0, (void **)&mem[i]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - if (!invalidate) - return 0; - - for (int i = 0; i < nb_buffers; i++) { - const VkMappedMemoryRange ival_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, - .size = VK_WHOLE_SIZE, - }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - continue; - inval_list = av_fast_realloc(s->scratch, &s->scratch_size, - (++inval_count)*sizeof(*inval_list)); - if (!inval_list) - return AVERROR(ENOMEM); - inval_list[inval_count - 1] = ival_buf; - } - - if (inval_count) { - ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count, - inval_list); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - return 0; -} - -int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, - int flush) -{ - int err = 0; - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - VkMappedMemoryRange *flush_list = NULL; - int flush_count = 0; - - if (flush) { - for (int i = 0; i < nb_buffers; i++) { - const VkMappedMemoryRange flush_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, - .size = VK_WHOLE_SIZE, - }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - continue; - flush_list = av_fast_realloc(s->scratch, &s->scratch_size, - (++flush_count)*sizeof(*flush_list)); - if (!flush_list) - return AVERROR(ENOMEM); - flush_list[flush_count - 1] = flush_buf; - } - } - - if (flush_count) { - ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count, - flush_list); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n", - ff_vk_ret2str(ret)); - err = AVERROR_EXTERNAL; /* We still want to try to unmap them */ - } - } - - for (int i = 0; i < nb_buffers; i++) - vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem); - - return err; -} - -void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf) -{ - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - if (!buf) - return; - - if (buf->buf != VK_NULL_HANDLE) - vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); - if (buf->mem != VK_NULL_HANDLE) - vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); -} - -int ff_vk_add_push_constant(AVFilterContext *avctx, FFVulkanPipeline *pl, - int offset, int size, VkShaderStageFlagBits stage) -{ - VkPushConstantRange *pc; - - pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts), - pl->push_consts_num + 1); - if (!pl->push_consts) - return AVERROR(ENOMEM); - - pc = &pl->push_consts[pl->push_consts_num++]; - memset(pc, 0, sizeof(*pc)); - - pc->stageFlags = stage; - pc->offset = offset; - pc->size = size; - - return 0; -} - -FN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) -int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx, - FFVkQueueFamilyCtx *qf) -{ - VkResult ret; - FFVkExecContext *e; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - VkCommandPoolCreateInfo cqueue_create = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = qf->queue_family, - }; - VkCommandBufferAllocateInfo cbuf_create = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = qf->nb_queues, - }; - - e = create_exec_ctx(s); - if (!e) - return AVERROR(ENOMEM); - - e->qf = qf; - - e->queues = av_mallocz(qf->nb_queues * sizeof(*e->queues)); - if (!e->queues) - return AVERROR(ENOMEM); - - e->bufs = av_mallocz(qf->nb_queues * sizeof(*e->bufs)); - if (!e->bufs) - return AVERROR(ENOMEM); - - /* Create command pool */ - ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create, - s->hwctx->alloc, &e->pool); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Command pool creation failure: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - cbuf_create.commandPool = e->pool; - - /* Allocate command buffer */ - ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - for (int i = 0; i < qf->nb_queues; i++) { - FFVkQueueCtx *q = &e->queues[i]; - vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, - i % qf->actual_queues, &q->queue); - } - - *ctx = e; - - return 0; -} - -void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e) -{ - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - - for (int j = 0; j < q->nb_buf_deps; j++) - av_buffer_unref(&q->buf_deps[j]); - q->nb_buf_deps = 0; - - for (int j = 0; j < q->nb_frame_deps; j++) - av_frame_free(&q->frame_deps[j]); - q->nb_frame_deps = 0; - - e->sem_wait_cnt = 0; - e->sem_sig_cnt = 0; -} - -int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) -{ - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - - VkCommandBufferBeginInfo cmd_start = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - }; - - /* Create the fence and don't wait for it initially */ - if (!q->fence) { - VkFenceCreateInfo fence_spawn = { - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - }; - ret = vk->CreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc, - &q->fence); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } else { - vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); - } - - /* Discard queue dependencies */ - ff_vk_discard_exec_deps(avctx, e); - - ret = vk->BeginCommandBuffer(e->bufs[e->qf->cur_queue], &cmd_start); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to start command recoding: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - return 0; -} - -VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e) -{ - return e->bufs[e->qf->cur_queue]; -} - -int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, - AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag) -{ - AVFrame **dst; - AVVkFrame *f = (AVVkFrame *)frame->data[0]; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data; - int planes = av_pix_fmt_count_planes(fc->sw_format); - - for (int i = 0; i < planes; i++) { - e->sem_wait = av_fast_realloc(e->sem_wait, &e->sem_wait_alloc, - (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait)); - if (!e->sem_wait) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_wait_dst = av_fast_realloc(e->sem_wait_dst, &e->sem_wait_dst_alloc, - (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_dst)); - if (!e->sem_wait_dst) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_wait_val = av_fast_realloc(e->sem_wait_val, &e->sem_wait_val_alloc, - (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_val)); - if (!e->sem_wait_val) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_sig = av_fast_realloc(e->sem_sig, &e->sem_sig_alloc, - (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig)); - if (!e->sem_sig) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_sig_val = av_fast_realloc(e->sem_sig_val, &e->sem_sig_val_alloc, - (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val)); - if (!e->sem_sig_val) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_sig_val_dst = av_fast_realloc(e->sem_sig_val_dst, &e->sem_sig_val_dst_alloc, - (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val_dst)); - if (!e->sem_sig_val_dst) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_wait[e->sem_wait_cnt] = f->sem[i]; - e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag; - e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i]; - e->sem_wait_cnt++; - - e->sem_sig[e->sem_sig_cnt] = f->sem[i]; - e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i] + 1; - e->sem_sig_val_dst[e->sem_sig_cnt] = &f->sem_value[i]; - e->sem_sig_cnt++; - } - - dst = av_fast_realloc(q->frame_deps, &q->frame_deps_alloc_size, - (q->nb_frame_deps + 1) * sizeof(*dst)); - if (!dst) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - q->frame_deps = dst; - q->frame_deps[q->nb_frame_deps] = av_frame_clone(frame); - if (!q->frame_deps[q->nb_frame_deps]) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - q->nb_frame_deps++; - - return 0; -} - -int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) -{ - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - - VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { - .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, - .pWaitSemaphoreValues = e->sem_wait_val, - .pSignalSemaphoreValues = e->sem_sig_val, - .waitSemaphoreValueCount = e->sem_wait_cnt, - .signalSemaphoreValueCount = e->sem_sig_cnt, - }; - - VkSubmitInfo s_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = &s_timeline_sem_info, - - .commandBufferCount = 1, - .pCommandBuffers = &e->bufs[e->qf->cur_queue], - - .pWaitSemaphores = e->sem_wait, - .pWaitDstStageMask = e->sem_wait_dst, - .waitSemaphoreCount = e->sem_wait_cnt, - - .pSignalSemaphores = e->sem_sig, - .signalSemaphoreCount = e->sem_sig_cnt, - }; - - ret = vk->EndCommandBuffer(e->bufs[e->qf->cur_queue]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - for (int i = 0; i < e->sem_sig_cnt; i++) - *e->sem_sig_val_dst[i] += 1; - - return 0; -} - -int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e, - AVBufferRef **deps, int nb_deps) -{ - AVBufferRef **dst; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - - if (!deps || !nb_deps) - return 0; - - dst = av_fast_realloc(q->buf_deps, &q->buf_deps_alloc_size, - (q->nb_buf_deps + nb_deps) * sizeof(*dst)); - if (!dst) - goto err; - - q->buf_deps = dst; - - for (int i = 0; i < nb_deps; i++) { - q->buf_deps[q->nb_buf_deps] = deps[i]; - if (!q->buf_deps[q->nb_buf_deps]) - goto err; - q->nb_buf_deps++; - } - - return 0; - -err: - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); -} +#include "libavutil/vulkan.c" static int vulkan_filter_set_device(AVFilterContext *avctx, AVBufferRef *device) @@ -844,741 +193,3 @@ int ff_vk_filter_init(AVFilterContext *avctx) return 0; } - -FN_CREATING(FFVulkanContext, FFVkSampler, sampler, samplers, samplers_num) -FFVkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, - VkFilter filt) -{ - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - VkSamplerCreateInfo sampler_info = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .magFilter = filt, - .minFilter = sampler_info.magFilter, - .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST : - VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - .addressModeV = sampler_info.addressModeU, - .addressModeW = sampler_info.addressModeU, - .anisotropyEnable = VK_FALSE, - .compareOp = VK_COMPARE_OP_NEVER, - .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - .unnormalizedCoordinates = unnorm_coords, - }; - - FFVkSampler *sctx = create_sampler(s); - if (!sctx) - return NULL; - - ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info, - s->hwctx->alloc, &sctx->sampler[0]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init sampler: %s\n", - ff_vk_ret2str(ret)); - return NULL; - } - - for (int i = 1; i < 4; i++) - sctx->sampler[i] = sctx->sampler[0]; - - return sctx; -} - -int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt) -{ - if (pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA || - pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_RGB24 || - pix_fmt == AV_PIX_FMT_BGR24 || pix_fmt == AV_PIX_FMT_RGB48 || - pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 || - pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0 || - pix_fmt == AV_PIX_FMT_0BGR || pix_fmt == AV_PIX_FMT_RGB0) - return 1; - return 0; -} - -const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixfmt); - const int high = desc->comp[0].depth > 8; - return high ? "rgba16f" : "rgba8"; -} - -typedef struct ImageViewCtx { - VkImageView view; -} ImageViewCtx; - -static void destroy_imageview(void *opaque, uint8_t *data) -{ - FFVulkanContext *s = opaque; - FFVulkanFunctions *vk = &s->vkfn; - ImageViewCtx *iv = (ImageViewCtx *)data; - - vk->DestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc); - av_free(iv); -} - -int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, - VkImageView *v, VkImage img, VkFormat fmt, - const VkComponentMapping map) -{ - int err; - AVBufferRef *buf; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - VkImageViewCreateInfo imgview_spawn = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = NULL, - .image = img, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = fmt, - .components = map, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - - ImageViewCtx *iv = av_mallocz(sizeof(*iv)); - - VkResult ret = vk->CreateImageView(s->hwctx->act_dev, &imgview_spawn, - s->hwctx->alloc, &iv->view); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create imageview: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0); - if (!buf) { - destroy_imageview(s, (uint8_t *)iv); - return AVERROR(ENOMEM); - } - - /* Add to queue dependencies */ - err = ff_vk_add_dep_exec_ctx(avctx, e, &buf, 1); - if (err) { - av_buffer_unref(&buf); - return err; - } - - *v = iv->view; - - return 0; -} - -FN_CREATING(FFVulkanPipeline, FFSPIRVShader, shader, shaders, shaders_num) -FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, FFVulkanPipeline *pl, - const char *name, VkShaderStageFlags stage) -{ - FFSPIRVShader *shd = create_shader(pl); - if (!shd) - return NULL; - - av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED); - - shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shd->shader.stage = stage; - - shd->name = name; - - GLSLF(0, #version %i ,460); - GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) ); - GLSLC(0, ); - - return shd; -} - -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, - int local_size[3]) -{ - shd->local_size[0] = local_size[0]; - shd->local_size[1] = local_size[1]; - shd->local_size[2] = local_size[2]; - - av_bprintf(&shd->src, "layout (local_size_x = %i, " - "local_size_y = %i, local_size_z = %i) in;\n\n", - shd->local_size[0], shd->local_size[1], shd->local_size[2]); -} - -void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio) -{ - int line = 0; - const char *p = shd->src.str; - const char *start = p; - - AVBPrint buf; - av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - - for (int i = 0; i < strlen(p); i++) { - if (p[i] == '\n') { - av_bprintf(&buf, "%i\t", ++line); - av_bprint_append_data(&buf, start, &p[i] - start + 1); - start = &p[i + 1]; - } - } - - av_log(avctx, prio, "Shader %s: \n%s", shd->name, buf.str); - av_bprint_finalize(&buf, NULL); -} - -int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, - const char *entrypoint) -{ - int err; - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - VkShaderModuleCreateInfo shader_create; - uint8_t *spirv; - size_t spirv_size; - void *priv; - - shd->shader.pName = entrypoint; - - err = ff_vk_glslang_shader_compile(avctx, shd, &spirv, &spirv_size, &priv); - if (err < 0) - return err; - - ff_vk_print_shader(avctx, shd, AV_LOG_VERBOSE); - - av_log(avctx, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", - shd->name, spirv_size); - - shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_create.pNext = NULL; - shader_create.codeSize = spirv_size; - shader_create.flags = 0; - shader_create.pCode = (void *)spirv; - - ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, - &shd->shader.module); - - ff_vk_glslang_shader_free(priv); - - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to create shader module: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - return 0; -} - -static const struct descriptor_props { - size_t struct_size; /* Size of the opaque which updates the descriptor */ - const char *type; - int is_uniform; - int mem_quali; /* Can use a memory qualifier */ - int dim_needed; /* Must indicate dimension */ - int buf_content; /* Must indicate buffer contents */ -} descriptor_props[] = { - [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, }, - [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, }, - [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, }, - [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, }, - [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, }, - [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, - [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, - [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, - [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, - [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, }, - [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, }, -}; - -int ff_vk_add_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, - FFSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, - int num, int only_print_to_shader) -{ - VkResult ret; - VkDescriptorSetLayout *layout; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - if (only_print_to_shader) - goto print; - - pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout), - pl->desc_layout_num + pl->qf->nb_queues); - if (!pl->desc_layout) - return AVERROR(ENOMEM); - - pl->desc_set_initialized = av_realloc_array(pl->desc_set_initialized, - sizeof(*pl->desc_set_initialized), - pl->descriptor_sets_num + 1); - if (!pl->desc_set_initialized) - return AVERROR(ENOMEM); - - pl->desc_set_initialized[pl->descriptor_sets_num] = 0; - layout = &pl->desc_layout[pl->desc_layout_num]; - - { /* Create descriptor set layout descriptions */ - VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 }; - VkDescriptorSetLayoutBinding *desc_binding; - - desc_binding = av_mallocz(sizeof(*desc_binding)*num); - if (!desc_binding) - return AVERROR(ENOMEM); - - for (int i = 0; i < num; i++) { - desc_binding[i].binding = i; - desc_binding[i].descriptorType = desc[i].type; - desc_binding[i].descriptorCount = FFMAX(desc[i].elems, 1); - desc_binding[i].stageFlags = desc[i].stages; - desc_binding[i].pImmutableSamplers = desc[i].sampler ? - desc[i].sampler->sampler : - NULL; - } - - desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - desc_create_layout.pBindings = desc_binding; - desc_create_layout.bindingCount = num; - - for (int i = 0; i < pl->qf->nb_queues; i++) { - ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, - s->hwctx->alloc, &layout[i]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " - "layout: %s\n", ff_vk_ret2str(ret)); - av_free(desc_binding); - return AVERROR_EXTERNAL; - } - } - - av_free(desc_binding); - } - - { /* Pool each descriptor by type and update pool counts */ - for (int i = 0; i < num; i++) { - int j; - for (j = 0; j < pl->pool_size_desc_num; j++) - if (pl->pool_size_desc[j].type == desc[i].type) - break; - if (j >= pl->pool_size_desc_num) { - pl->pool_size_desc = av_realloc_array(pl->pool_size_desc, - sizeof(*pl->pool_size_desc), - ++pl->pool_size_desc_num); - if (!pl->pool_size_desc) - return AVERROR(ENOMEM); - memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize)); - } - pl->pool_size_desc[j].type = desc[i].type; - pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1)*pl->qf->nb_queues; - } - } - - { /* Create template creation struct */ - VkDescriptorUpdateTemplateCreateInfo *dt; - VkDescriptorUpdateTemplateEntry *des_entries; - - /* Freed after descriptor set initialization */ - des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry)); - if (!des_entries) - return AVERROR(ENOMEM); - - for (int i = 0; i < num; i++) { - des_entries[i].dstBinding = i; - des_entries[i].descriptorType = desc[i].type; - des_entries[i].descriptorCount = FFMAX(desc[i].elems, 1); - des_entries[i].dstArrayElement = 0; - des_entries[i].offset = ((uint8_t *)desc[i].updater) - (uint8_t *)s; - des_entries[i].stride = descriptor_props[desc[i].type].struct_size; - } - - pl->desc_template_info = av_realloc_array(pl->desc_template_info, - sizeof(*pl->desc_template_info), - pl->total_descriptor_sets + pl->qf->nb_queues); - if (!pl->desc_template_info) - return AVERROR(ENOMEM); - - dt = &pl->desc_template_info[pl->total_descriptor_sets]; - memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues); - - for (int i = 0; i < pl->qf->nb_queues; i++) { - dt[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; - dt[i].templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; - dt[i].descriptorSetLayout = layout[i]; - dt[i].pDescriptorUpdateEntries = des_entries; - dt[i].descriptorUpdateEntryCount = num; - } - } - - pl->descriptor_sets_num++; - - pl->desc_layout_num += pl->qf->nb_queues; - pl->total_descriptor_sets += pl->qf->nb_queues; - -print: - /* Write shader info */ - for (int i = 0; i < num; i++) { - const struct descriptor_props *prop = &descriptor_props[desc[i].type]; - GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i); - - if (desc[i].mem_layout) - GLSLA(", %s", desc[i].mem_layout); - GLSLA(")"); - - if (prop->is_uniform) - GLSLA(" uniform"); - - if (prop->mem_quali && desc[i].mem_quali) - GLSLA(" %s", desc[i].mem_quali); - - if (prop->type) - GLSLA(" %s", prop->type); - - if (prop->dim_needed) - GLSLA("%iD", desc[i].dimensions); - - GLSLA(" %s", desc[i].name); - - if (prop->buf_content) - GLSLA(" {\n %s\n}", desc[i].buf_content); - else if (desc[i].elems > 0) - GLSLA("[%i]", desc[i].elems); - - GLSLA(";\n"); - } - GLSLA("\n"); - - return 0; -} - -void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, - int set_id) -{ - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - /* If a set has never been updated, update all queues' sets. */ - if (!pl->desc_set_initialized[set_id]) { - for (int i = 0; i < pl->qf->nb_queues; i++) { - int idx = set_id*pl->qf->nb_queues + i; - vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, - pl->desc_set[idx], - pl->desc_template[idx], - s); - } - pl->desc_set_initialized[set_id] = 1; - return; - } - - set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue; - - vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, - pl->desc_set[set_id], - pl->desc_template[set_id], - s); -} - -void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, - VkShaderStageFlagBits stage, int offset, - size_t size, void *src) -{ - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout, - stage, offset, size, src); -} - -int ff_vk_init_pipeline_layout(AVFilterContext *avctx, FFVulkanPipeline *pl) -{ - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - pl->desc_staging = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_staging)); - if (!pl->desc_staging) - return AVERROR(ENOMEM); - - { /* Init descriptor set pool */ - VkDescriptorPoolCreateInfo pool_create_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .poolSizeCount = pl->pool_size_desc_num, - .pPoolSizes = pl->pool_size_desc, - .maxSets = pl->total_descriptor_sets, - }; - - ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, - s->hwctx->alloc, &pl->desc_pool); - av_freep(&pl->pool_size_desc); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " - "pool: %s\n", ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Allocate descriptor sets */ - VkDescriptorSetAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = pl->desc_pool, - .descriptorSetCount = pl->total_descriptor_sets, - .pSetLayouts = pl->desc_layout, - }; - - pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set)); - if (!pl->desc_set) - return AVERROR(ENOMEM); - - ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &alloc_info, - pl->desc_set); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Finally create the pipeline layout */ - VkPipelineLayoutCreateInfo spawn_pipeline_layout = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .pSetLayouts = (VkDescriptorSetLayout *)pl->desc_staging, - .pushConstantRangeCount = pl->push_consts_num, - .pPushConstantRanges = pl->push_consts, - }; - - for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) - pl->desc_staging[spawn_pipeline_layout.setLayoutCount++] = pl->desc_layout[i]; - - ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, - s->hwctx->alloc, &pl->pipeline_layout); - av_freep(&pl->push_consts); - pl->push_consts_num = 0; - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Descriptor template (for tightly packed descriptors) */ - VkDescriptorUpdateTemplateCreateInfo *dt; - - pl->desc_template = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_template)); - if (!pl->desc_template) - return AVERROR(ENOMEM); - - /* Create update templates for the descriptor sets */ - for (int i = 0; i < pl->total_descriptor_sets; i++) { - dt = &pl->desc_template_info[i]; - dt->pipelineLayout = pl->pipeline_layout; - ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev, - dt, s->hwctx->alloc, - &pl->desc_template[i]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor " - "template: %s\n", ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - /* Free the duplicated memory used for the template entries */ - for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { - dt = &pl->desc_template_info[i]; - av_free((void *)dt->pDescriptorUpdateEntries); - } - - av_freep(&pl->desc_template_info); - } - - return 0; -} - -FN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num) -FFVulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx, - FFVkQueueFamilyCtx *qf) -{ - FFVulkanPipeline *pl = create_pipeline(avctx->priv); - if (pl) - pl->qf = qf; - - return pl; -} - -int ff_vk_init_compute_pipeline(AVFilterContext *avctx, FFVulkanPipeline *pl) -{ - int i; - VkResult ret; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - VkComputePipelineCreateInfo pipe = { - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .layout = pl->pipeline_layout, - }; - - for (i = 0; i < pl->shaders_num; i++) { - if (pl->shaders[i]->shader.stage & VK_SHADER_STAGE_COMPUTE_BIT) { - pipe.stage = pl->shaders[i]->shader; - break; - } - } - if (i == pl->shaders_num) { - av_log(avctx, AV_LOG_ERROR, "Can't init compute pipeline, no shader\n"); - return AVERROR(EINVAL); - } - - ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe, - s->hwctx->alloc, &pl->pipeline); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; - - return 0; -} - -void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, - FFVulkanPipeline *pl) -{ - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - vk->CmdBindPipeline(e->bufs[e->qf->cur_queue], pl->bind_point, pl->pipeline); - - for (int i = 0; i < pl->descriptor_sets_num; i++) - pl->desc_staging[i] = pl->desc_set[i*pl->qf->nb_queues + pl->qf->cur_queue]; - - vk->CmdBindDescriptorSets(e->bufs[e->qf->cur_queue], pl->bind_point, - pl->pipeline_layout, 0, - pl->descriptor_sets_num, - (VkDescriptorSet *)pl->desc_staging, - 0, NULL); - - e->bound_pl = pl; -} - -static void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) -{ - FFVulkanFunctions *vk = &s->vkfn; - - /* Make sure all queues have finished executing */ - for (int i = 0; i < e->qf->nb_queues; i++) { - FFVkQueueCtx *q = &e->queues[i]; - - if (q->fence) { - vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); - } - - /* Free the fence */ - if (q->fence) - vk->DestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc); - - /* Free buffer dependencies */ - for (int j = 0; j < q->nb_buf_deps; j++) - av_buffer_unref(&q->buf_deps[j]); - av_free(q->buf_deps); - - /* Free frame dependencies */ - for (int j = 0; j < q->nb_frame_deps; j++) - av_frame_free(&q->frame_deps[j]); - av_free(q->frame_deps); - } - - if (e->bufs) - vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, e->qf->nb_queues, e->bufs); - if (e->pool) - vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); - - av_freep(&e->bufs); - av_freep(&e->queues); - av_freep(&e->sem_sig); - av_freep(&e->sem_sig_val); - av_freep(&e->sem_sig_val_dst); - av_freep(&e->sem_wait); - av_freep(&e->sem_wait_dst); - av_freep(&e->sem_wait_val); - av_free(e); -} - -static void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) -{ - FFVulkanFunctions *vk = &s->vkfn; - - for (int i = 0; i < pl->shaders_num; i++) { - FFSPIRVShader *shd = pl->shaders[i]; - av_bprint_finalize(&shd->src, NULL); - vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, - s->hwctx->alloc); - av_free(shd); - } - - vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); - vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout, - s->hwctx->alloc); - - for (int i = 0; i < pl->desc_layout_num; i++) { - if (pl->desc_template && pl->desc_template[i]) - vk->DestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i], - s->hwctx->alloc); - if (pl->desc_layout && pl->desc_layout[i]) - vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i], - s->hwctx->alloc); - } - - /* Also frees the descriptor sets */ - if (pl->desc_pool) - vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, - s->hwctx->alloc); - - av_freep(&pl->desc_staging); - av_freep(&pl->desc_set); - av_freep(&pl->shaders); - av_freep(&pl->desc_layout); - av_freep(&pl->desc_template); - av_freep(&pl->desc_set_initialized); - av_freep(&pl->push_consts); - pl->push_consts_num = 0; - - /* Only freed in case of failure */ - av_freep(&pl->pool_size_desc); - if (pl->desc_template_info) { - for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { - VkDescriptorUpdateTemplateCreateInfo *dt = &pl->desc_template_info[i]; - av_free((void *)dt->pDescriptorUpdateEntries); - } - av_freep(&pl->desc_template_info); - } - - av_free(pl); -} - -void ff_vk_filter_uninit(AVFilterContext *avctx) -{ - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - - ff_vk_glslang_uninit(); - - for (int i = 0; i < s->exec_ctx_num; i++) - free_exec_ctx(s, s->exec_ctx[i]); - av_freep(&s->exec_ctx); - - for (int i = 0; i < s->samplers_num; i++) { - vk->DestroySampler(s->hwctx->act_dev, s->samplers[i]->sampler[0], - s->hwctx->alloc); - av_free(s->samplers[i]); - } - av_freep(&s->samplers); - - for (int i = 0; i < s->pipelines_num; i++) - free_pipeline(s, s->pipelines[i]); - av_freep(&s->pipelines); - - av_freep(&s->scratch); - s->scratch_size = 0; - - av_buffer_unref(&s->device_ref); - av_buffer_unref(&s->frames_ref); -} diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index df0e830af8..39c139cafa 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -19,197 +19,8 @@ #ifndef AVFILTER_VULKAN_H #define AVFILTER_VULKAN_H -#define VK_NO_PROTOTYPES -#define VK_ENABLE_BETA_EXTENSIONS - #include "avfilter.h" -#include "libavutil/pixdesc.h" -#include "libavutil/bprint.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_vulkan.h" -#include "libavutil/vulkan_functions.h" - -/* GLSL management macros */ -#define INDENT(N) INDENT_##N -#define INDENT_0 -#define INDENT_1 INDENT_0 " " -#define INDENT_2 INDENT_1 INDENT_1 -#define INDENT_3 INDENT_2 INDENT_1 -#define INDENT_4 INDENT_3 INDENT_1 -#define INDENT_5 INDENT_4 INDENT_1 -#define INDENT_6 INDENT_5 INDENT_1 -#define C(N, S) INDENT(N) #S "\n" -#define GLSLC(N, S) av_bprintf(&shd->src, C(N, S)) -#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__) -#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__) -#define GLSLD(D) GLSLC(0, ); \ - av_bprint_append_data(&shd->src, D, strlen(D)); \ - GLSLC(0, ) - -/* Helper, pretty much every Vulkan return value needs to be checked */ -#define RET(x) \ - do { \ - if ((err = (x)) < 0) \ - goto fail; \ - } while (0) - -typedef struct FFSPIRVShader { - const char *name; /* Name for id/debugging purposes */ - AVBPrint src; - int local_size[3]; /* Compute shader workgroup sizes */ - VkPipelineShaderStageCreateInfo shader; -} FFSPIRVShader; - -typedef struct FFVkSampler { - VkSampler sampler[4]; -} FFVkSampler; - -typedef struct FFVulkanDescriptorSetBinding { - const char *name; - VkDescriptorType type; - const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */ - const char *mem_quali; /* readonly, writeonly, etc. */ - const char *buf_content; /* For buffers */ - uint32_t dimensions; /* Needed for e.g. sampler%iD */ - uint32_t elems; /* 0 - scalar, 1 or more - vector */ - VkShaderStageFlags stages; - FFVkSampler *sampler; /* Sampler to use for all elems */ - void *updater; /* Pointer to VkDescriptor*Info */ -} FFVulkanDescriptorSetBinding; - -typedef struct FFVkBuffer { - VkBuffer buf; - VkDeviceMemory mem; - VkMemoryPropertyFlagBits flags; -} FFVkBuffer; - -typedef struct FFVkQueueFamilyCtx { - int queue_family; - int nb_queues; - int cur_queue; - int actual_queues; -} FFVkQueueFamilyCtx; - -typedef struct FFVulkanPipeline { - FFVkQueueFamilyCtx *qf; - - VkPipelineBindPoint bind_point; - - /* Contexts */ - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - - /* Shaders */ - FFSPIRVShader **shaders; - int shaders_num; - - /* Push consts */ - VkPushConstantRange *push_consts; - int push_consts_num; - - /* Descriptors */ - VkDescriptorSetLayout *desc_layout; - VkDescriptorPool desc_pool; - VkDescriptorSet *desc_set; - void **desc_staging; - VkDescriptorSetLayoutBinding **desc_binding; - VkDescriptorUpdateTemplate *desc_template; - int *desc_set_initialized; - int desc_layout_num; - int descriptor_sets_num; - int total_descriptor_sets; - int pool_size_desc_num; - - /* Temporary, used to store data in between initialization stages */ - VkDescriptorUpdateTemplateCreateInfo *desc_template_info; - VkDescriptorPoolSize *pool_size_desc; -} FFVulkanPipeline; - -typedef struct FFVkQueueCtx { - VkFence fence; - VkQueue queue; - - /* Buffer dependencies */ - AVBufferRef **buf_deps; - int nb_buf_deps; - int buf_deps_alloc_size; - - /* Frame dependencies */ - AVFrame **frame_deps; - int nb_frame_deps; - int frame_deps_alloc_size; -} FFVkQueueCtx; - -typedef struct FFVkExecContext { - FFVkQueueFamilyCtx *qf; - - VkCommandPool pool; - VkCommandBuffer *bufs; - FFVkQueueCtx *queues; - - AVBufferRef ***deps; - int *nb_deps; - int *dep_alloc_size; - - FFVulkanPipeline *bound_pl; - - VkSemaphore *sem_wait; - int sem_wait_alloc; /* Allocated sem_wait */ - int sem_wait_cnt; - - uint64_t *sem_wait_val; - int sem_wait_val_alloc; - - VkPipelineStageFlagBits *sem_wait_dst; - int sem_wait_dst_alloc; /* Allocated sem_wait_dst */ - - VkSemaphore *sem_sig; - int sem_sig_alloc; /* Allocated sem_sig */ - int sem_sig_cnt; - - uint64_t *sem_sig_val; - int sem_sig_val_alloc; - - uint64_t **sem_sig_val_dst; - int sem_sig_val_dst_alloc; -} FFVkExecContext; - -typedef struct FFVulkanContext { - const AVClass *class; - FFVulkanFunctions vkfn; - FFVulkanExtensions extensions; - VkPhysicalDeviceProperties props; - VkPhysicalDeviceMemoryProperties mprops; - - AVBufferRef *device_ref; - AVBufferRef *frames_ref; /* For in-place filtering */ - AVHWDeviceContext *device; - AVVulkanDeviceContext *hwctx; - - /* Properties */ - int output_width; - int output_height; - enum AVPixelFormat output_format; - enum AVPixelFormat input_format; - - /* Samplers */ - FFVkSampler **samplers; - int samplers_num; - - /* Exec contexts */ - FFVkExecContext **exec_ctx; - int exec_ctx_num; - - /* Pipelines (each can have 1 shader of each type) */ - FFVulkanPipeline **pipelines; - int pipelines_num; - - void *scratch; /* Scratch memory used only in functions */ - unsigned int scratch_size; -} FFVulkanContext; - -/* Identity mapping - r = r, b = b, g = g, a = a */ -extern const VkComponentMapping ff_comp_identity_map; +#include "libavutil/vulkan.h" /** * General lavfi IO functions @@ -218,194 +29,5 @@ int ff_vk_filter_init (AVFilterContext *avctx); int ff_vk_filter_config_input (AVFilterLink *inlink); int ff_vk_filter_config_output (AVFilterLink *outlink); int ff_vk_filter_config_output_inplace(AVFilterLink *outlink); -void ff_vk_filter_uninit (AVFilterContext *avctx); - -/** - * Converts Vulkan return values to strings - */ -const char *ff_vk_ret2str(VkResult res); - -/** - * Returns 1 if the image is any sort of supported RGB - */ -int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); - -/** - * Gets the glsl format string for a pixel format - */ -const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); - -/** - * Initialize a queue family with a specific number of queues. - * If nb_queues == 0, use however many queues the queue family has. - */ -void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int nb_queues); - -/** - * Rotate through the queues in a queue family. - */ -void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf); - -/** - * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() - */ -FFVkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, - VkFilter filt); - -/** - * Create an imageview. - * Guaranteed to remain alive until the queue submission has finished executing, - * and will be destroyed after that. - */ -int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, - VkImageView *v, VkImage img, VkFormat fmt, - const VkComponentMapping map); - -/** - * Define a push constant for a given stage into a pipeline. - * Must be called before the pipeline layout has been initialized. - */ -int ff_vk_add_push_constant(AVFilterContext *avctx, FFVulkanPipeline *pl, - int offset, int size, VkShaderStageFlagBits stage); - -/** - * Inits a pipeline. Everything in it will be auto-freed when calling - * ff_vk_filter_uninit(). - */ -FFVulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx, - FFVkQueueFamilyCtx *qf); - -/** - * Inits a shader for a specific pipeline. Will be auto-freed on uninit. - */ -FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, FFVulkanPipeline *pl, - const char *name, VkShaderStageFlags stage); - -/** - * Writes the workgroup size for a shader. - */ -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, - int local_size[3]); - -/** - * Adds a descriptor set to the shader and registers them in the pipeline. - */ -int ff_vk_add_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, - FFSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, - int num, int only_print_to_shader); - -/** - * Compiles the shader, entrypoint must be set to "main". - */ -int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, - const char *entrypoint); - -/** - * Pretty print shader, mainly used by shader compilers. - */ -void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio); - -/** - * Initializes the pipeline layout after all shaders and descriptor sets have - * been finished. - */ -int ff_vk_init_pipeline_layout(AVFilterContext *avctx, FFVulkanPipeline *pl); - -/** - * Initializes a compute pipeline. Will pick the first shader with the - * COMPUTE flag set. - */ -int ff_vk_init_compute_pipeline(AVFilterContext *avctx, FFVulkanPipeline *pl); - -/** - * Updates a descriptor set via the updaters defined. - * Can be called immediately after pipeline creation, but must be called - * at least once before queue submission. - */ -void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl, - int set_id); - -/** - * Init an execution context for command recording and queue submission. - * WIll be auto-freed on uninit. - */ -int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx, - FFVkQueueFamilyCtx *qf); - -/** - * Begin recording to the command buffer. Previous execution must have been - * completed, which ff_vk_submit_exec_queue() will ensure. - */ -int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Add a command to bind the completed pipeline and its descriptor sets. - * Must be called after ff_vk_start_exec_recording() and before submission. - */ -void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, - FFVulkanPipeline *pl); - -/** - * Updates push constants. - * Must be called after binding a pipeline if any push constants were defined. - */ -void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, - VkShaderStageFlagBits stage, int offset, - size_t size, void *src); - -/** - * Gets the command buffer to use for this submission from the exe context. - */ -VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Adds a generic AVBufferRef as a queue depenency. - */ -int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e, - AVBufferRef **deps, int nb_deps); - -/** - * Discards all queue dependencies - */ -void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Adds a frame as a queue dependency. This also manages semaphore signalling. - * Must be called before submission. - */ -int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, - AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag); - -/** - * Submits a command buffer to the queue for execution. - * Will block until execution has finished in order to simplify resource - * management. - */ -int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Create a VkBuffer with the specified parameters. - */ -int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, - VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); - -/** - * Maps the buffer to userspace. Set invalidate to 1 if reading the contents - * is necessary. - */ -int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], - int nb_buffers, int invalidate); - -/** - * Unmaps the buffer from userspace. Set flush to 1 to write and sync. - */ -int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, - int flush); - -/** - * Frees a buffer. - */ -void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf); #endif /* AVFILTER_VULKAN_H */ diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index b218b6c411..1e352d5ef7 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -38,6 +38,7 @@ #include "hwcontext_internal.h" #include "hwcontext_vulkan.h" +#include "vulkan.h" #include "vulkan_loader.h" #if CONFIG_LIBDRM @@ -131,11 +132,6 @@ typedef struct AVVkFrameInternal { #endif } AVVkFrameInternal; -#define DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ - VK_IMAGE_USAGE_STORAGE_BIT | \ - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \ - VK_IMAGE_USAGE_TRANSFER_DST_BIT) - #define ADD_VAL_TO_LIST(list, count, val) \ do { \ list = av_realloc_array(list, sizeof(*list), ++count); \ @@ -251,7 +247,7 @@ static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, fmt[i], &prop); flags = linear ? prop.formatProperties.linearTilingFeatures : prop.formatProperties.optimalTilingFeatures; - if (!(flags & DEFAULT_USAGE_FLAGS)) + if (!(flags & FF_VK_DEFAULT_USAGE_FLAGS)) return 0; } @@ -2041,7 +2037,7 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; if (!hwctx->usage) - hwctx->usage = DEFAULT_USAGE_FLAGS; + hwctx->usage = FF_VK_DEFAULT_USAGE_FLAGS; err = create_exec_ctx(hwfc, &fp->conv_ctx, dev_hwctx->queue_family_comp_index, diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c new file mode 100644 index 0000000000..fba9543cce --- /dev/null +++ b/libavutil/vulkan.c @@ -0,0 +1,1392 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vulkan.h" +#include "vulkan_glslang.h" + +#include "avassert.h" +#include "vulkan_loader.h" + +/* Generic macro for creating contexts which need to keep their addresses + * if another context is created. */ +#define FN_CREATING(ctx, type, shortname, array, num) \ +static av_always_inline type *create_ ##shortname(ctx *dctx) \ +{ \ + type **array, *sctx = av_mallocz(sizeof(*sctx)); \ + if (!sctx) \ + return NULL; \ + \ + array = av_realloc_array(dctx->array, sizeof(*dctx->array), dctx->num + 1);\ + if (!array) { \ + av_free(sctx); \ + return NULL; \ + } \ + \ + dctx->array = array; \ + dctx->array[dctx->num++] = sctx; \ + \ + return sctx; \ +} + +const VkComponentMapping ff_comp_identity_map = { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, +}; + +/* Converts return values to strings */ +const char *ff_vk_ret2str(VkResult res) +{ +#define CASE(VAL) case VAL: return #VAL + switch (res) { + CASE(VK_SUCCESS); + CASE(VK_NOT_READY); + CASE(VK_TIMEOUT); + CASE(VK_EVENT_SET); + CASE(VK_EVENT_RESET); + CASE(VK_INCOMPLETE); + CASE(VK_ERROR_OUT_OF_HOST_MEMORY); + CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY); + CASE(VK_ERROR_INITIALIZATION_FAILED); + CASE(VK_ERROR_DEVICE_LOST); + CASE(VK_ERROR_MEMORY_MAP_FAILED); + CASE(VK_ERROR_LAYER_NOT_PRESENT); + CASE(VK_ERROR_EXTENSION_NOT_PRESENT); + CASE(VK_ERROR_FEATURE_NOT_PRESENT); + CASE(VK_ERROR_INCOMPATIBLE_DRIVER); + CASE(VK_ERROR_TOO_MANY_OBJECTS); + CASE(VK_ERROR_FORMAT_NOT_SUPPORTED); + CASE(VK_ERROR_FRAGMENTED_POOL); + CASE(VK_ERROR_SURFACE_LOST_KHR); + CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); + CASE(VK_SUBOPTIMAL_KHR); + CASE(VK_ERROR_OUT_OF_DATE_KHR); + CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR); + CASE(VK_ERROR_VALIDATION_FAILED_EXT); + CASE(VK_ERROR_INVALID_SHADER_NV); + CASE(VK_ERROR_OUT_OF_POOL_MEMORY); + CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE); + CASE(VK_ERROR_NOT_PERMITTED_EXT); + default: return "Unknown error"; + } +#undef CASE +} + +void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int nb_queues) +{ + switch (dev_family) { + case VK_QUEUE_GRAPHICS_BIT: + qf->queue_family = s->hwctx->queue_family_index; + qf->actual_queues = s->hwctx->nb_graphics_queues; + break; + case VK_QUEUE_COMPUTE_BIT: + qf->queue_family = s->hwctx->queue_family_comp_index; + qf->actual_queues = s->hwctx->nb_comp_queues; + break; + case VK_QUEUE_TRANSFER_BIT: + qf->queue_family = s->hwctx->queue_family_tx_index; + qf->actual_queues = s->hwctx->nb_tx_queues; + break; + case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: + qf->queue_family = s->hwctx->queue_family_encode_index; + qf->actual_queues = s->hwctx->nb_encode_queues; + break; + case VK_QUEUE_VIDEO_DECODE_BIT_KHR: + qf->queue_family = s->hwctx->queue_family_decode_index; + qf->actual_queues = s->hwctx->nb_decode_queues; + break; + default: + av_assert0(0); /* Should never happen */ + } + + if (!nb_queues) + qf->nb_queues = qf->actual_queues; + else + qf->nb_queues = nb_queues; + + return; +} + +void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) +{ + qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues; +} + +static int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, + VkMemoryPropertyFlagBits req_flags, void *alloc_extension, + VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) +{ + VkResult ret; + int index = -1; + FFVulkanFunctions *vk = &s->vkfn; + + VkMemoryAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = alloc_extension, + }; + + /* Align if we need to */ + if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment); + + alloc_info.allocationSize = req->size; + + /* The vulkan spec requires memory types to be sorted in the "optimal" + * order, so the first matching type we find will be the best/fastest one */ + for (int i = 0; i < s->mprops.memoryTypeCount; i++) { + /* The memory type must be supported by the requirements (bitfield) */ + if (!(req->memoryTypeBits & (1 << i))) + continue; + + /* The memory type flags must include our properties */ + if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) + continue; + + /* Found a suitable memory type */ + index = i; + break; + } + + if (index < 0) { + av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", + req_flags); + return AVERROR(EINVAL); + } + + alloc_info.memoryTypeIndex = index; + + ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info, + s->hwctx->alloc, mem); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR(ENOMEM); + } + + *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; + + return 0; +} + +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) +{ + int err; + VkResult ret; + int use_ded_mem; + FFVulkanFunctions *vk = &s->vkfn; + + VkBufferCreateInfo buf_spawn = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = NULL, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .size = size, /* Gets FFALIGNED during alloc if host visible + but should be ok */ + }; + + VkBufferMemoryRequirementsInfo2 req_desc = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, + }; + VkMemoryDedicatedAllocateInfo ded_alloc = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = NULL, + }; + VkMemoryDedicatedRequirements ded_req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + }; + VkMemoryRequirements2 req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + .pNext = &ded_req, + }; + + ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + req_desc.buffer = buf->buf; + + vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req); + + /* In case the implementation prefers/requires dedicated allocation */ + use_ded_mem = ded_req.prefersDedicatedAllocation | + ded_req.requiresDedicatedAllocation; + if (use_ded_mem) + ded_alloc.buffer = buf->buf; + + err = vk_alloc_mem(s, &req.memoryRequirements, flags, + use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, + &buf->flags, &buf->mem); + if (err) + return err; + + ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], + int nb_buffers, int invalidate) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkMappedMemoryRange *inval_list = NULL; + int inval_count = 0; + + for (int i = 0; i < nb_buffers; i++) { + ret = vk->MapMemory(s->hwctx->act_dev, buf[i].mem, 0, + VK_WHOLE_SIZE, 0, (void **)&mem[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + if (!invalidate) + return 0; + + for (int i = 0; i < nb_buffers; i++) { + const VkMappedMemoryRange ival_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = buf[i].mem, + .size = VK_WHOLE_SIZE, + }; + if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + continue; + inval_list = av_fast_realloc(s->scratch, &s->scratch_size, + (++inval_count)*sizeof(*inval_list)); + if (!inval_list) + return AVERROR(ENOMEM); + inval_list[inval_count - 1] = ival_buf; + } + + if (inval_count) { + ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count, + inval_list); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + return 0; +} + +int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, + int flush) +{ + int err = 0; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkMappedMemoryRange *flush_list = NULL; + int flush_count = 0; + + if (flush) { + for (int i = 0; i < nb_buffers; i++) { + const VkMappedMemoryRange flush_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = buf[i].mem, + .size = VK_WHOLE_SIZE, + }; + if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + continue; + flush_list = av_fast_realloc(s->scratch, &s->scratch_size, + (++flush_count)*sizeof(*flush_list)); + if (!flush_list) + return AVERROR(ENOMEM); + flush_list[flush_count - 1] = flush_buf; + } + } + + if (flush_count) { + ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count, + flush_list); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR_EXTERNAL; /* We still want to try to unmap them */ + } + } + + for (int i = 0; i < nb_buffers; i++) + vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem); + + return err; +} + +void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) +{ + FFVulkanFunctions *vk = &s->vkfn; + + if (!buf) + return; + + vk->DeviceWaitIdle(s->hwctx->act_dev); + + if (buf->buf != VK_NULL_HANDLE) + vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); + if (buf->mem != VK_NULL_HANDLE) + vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); +} + +int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, + VkShaderStageFlagBits stage) +{ + VkPushConstantRange *pc; + + pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts), + pl->push_consts_num + 1); + if (!pl->push_consts) + return AVERROR(ENOMEM); + + pc = &pl->push_consts[pl->push_consts_num++]; + memset(pc, 0, sizeof(*pc)); + + pc->stageFlags = stage; + pc->offset = offset; + pc->size = size; + + return 0; +} + +FN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) +int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, + FFVkQueueFamilyCtx *qf) +{ + VkResult ret; + FFVkExecContext *e; + FFVulkanFunctions *vk = &s->vkfn; + + VkCommandPoolCreateInfo cqueue_create = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + .queueFamilyIndex = qf->queue_family, + }; + VkCommandBufferAllocateInfo cbuf_create = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = qf->nb_queues, + }; + + e = create_exec_ctx(s); + if (!e) + return AVERROR(ENOMEM); + + e->qf = qf; + + e->queues = av_mallocz(qf->nb_queues * sizeof(*e->queues)); + if (!e->queues) + return AVERROR(ENOMEM); + + e->bufs = av_mallocz(qf->nb_queues * sizeof(*e->bufs)); + if (!e->bufs) + return AVERROR(ENOMEM); + + /* Create command pool */ + ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create, + s->hwctx->alloc, &e->pool); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + cbuf_create.commandPool = e->pool; + + /* Allocate command buffer */ + ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + for (int i = 0; i < qf->nb_queues; i++) { + FFVkQueueCtx *q = &e->queues[i]; + vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, + i % qf->actual_queues, &q->queue); + } + + *ctx = e; + + return 0; +} + +void ff_vk_discard_exec_deps(FFVkExecContext *e) +{ + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + for (int j = 0; j < q->nb_buf_deps; j++) + av_buffer_unref(&q->buf_deps[j]); + q->nb_buf_deps = 0; + + for (int j = 0; j < q->nb_frame_deps; j++) + av_frame_free(&q->frame_deps[j]); + q->nb_frame_deps = 0; + + e->sem_wait_cnt = 0; + e->sem_sig_cnt = 0; +} + +int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + VkCommandBufferBeginInfo cmd_start = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + + /* Create the fence and don't wait for it initially */ + if (!q->fence) { + VkFenceCreateInfo fence_spawn = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + }; + ret = vk->CreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc, + &q->fence); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } else { + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); + } + + /* Discard queue dependencies */ + ff_vk_discard_exec_deps(e); + + ret = vk->BeginCommandBuffer(e->bufs[e->qf->cur_queue], &cmd_start); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e) +{ + return e->bufs[e->qf->cur_queue]; +} + +int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, + VkPipelineStageFlagBits in_wait_dst_flag) +{ + AVFrame **dst; + AVVkFrame *f = (AVVkFrame *)frame->data[0]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data; + int planes = av_pix_fmt_count_planes(fc->sw_format); + + for (int i = 0; i < planes; i++) { + e->sem_wait = av_fast_realloc(e->sem_wait, &e->sem_wait_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait)); + if (!e->sem_wait) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_wait_dst = av_fast_realloc(e->sem_wait_dst, &e->sem_wait_dst_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_dst)); + if (!e->sem_wait_dst) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_wait_val = av_fast_realloc(e->sem_wait_val, &e->sem_wait_val_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_val)); + if (!e->sem_wait_val) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_sig = av_fast_realloc(e->sem_sig, &e->sem_sig_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig)); + if (!e->sem_sig) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_sig_val = av_fast_realloc(e->sem_sig_val, &e->sem_sig_val_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val)); + if (!e->sem_sig_val) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_sig_val_dst = av_fast_realloc(e->sem_sig_val_dst, &e->sem_sig_val_dst_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val_dst)); + if (!e->sem_sig_val_dst) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_wait[e->sem_wait_cnt] = f->sem[i]; + e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag; + e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i]; + e->sem_wait_cnt++; + + e->sem_sig[e->sem_sig_cnt] = f->sem[i]; + e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i] + 1; + e->sem_sig_val_dst[e->sem_sig_cnt] = &f->sem_value[i]; + e->sem_sig_cnt++; + } + + dst = av_fast_realloc(q->frame_deps, &q->frame_deps_alloc_size, + (q->nb_frame_deps + 1) * sizeof(*dst)); + if (!dst) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + q->frame_deps = dst; + q->frame_deps[q->nb_frame_deps] = av_frame_clone(frame); + if (!q->frame_deps[q->nb_frame_deps]) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + q->nb_frame_deps++; + + return 0; +} + +int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pWaitSemaphoreValues = e->sem_wait_val, + .pSignalSemaphoreValues = e->sem_sig_val, + .waitSemaphoreValueCount = e->sem_wait_cnt, + .signalSemaphoreValueCount = e->sem_sig_cnt, + }; + + VkSubmitInfo s_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, + + .commandBufferCount = 1, + .pCommandBuffers = &e->bufs[e->qf->cur_queue], + + .pWaitSemaphores = e->sem_wait, + .pWaitDstStageMask = e->sem_wait_dst, + .waitSemaphoreCount = e->sem_wait_cnt, + + .pSignalSemaphores = e->sem_sig, + .signalSemaphoreCount = e->sem_sig_cnt, + }; + + ret = vk->EndCommandBuffer(e->bufs[e->qf->cur_queue]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + for (int i = 0; i < e->sem_sig_cnt; i++) + *e->sem_sig_val_dst[i] += 1; + + return 0; +} + +int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, + AVBufferRef **deps, int nb_deps) +{ + AVBufferRef **dst; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + if (!deps || !nb_deps) + return 0; + + dst = av_fast_realloc(q->buf_deps, &q->buf_deps_alloc_size, + (q->nb_buf_deps + nb_deps) * sizeof(*dst)); + if (!dst) + goto err; + + q->buf_deps = dst; + + for (int i = 0; i < nb_deps; i++) { + q->buf_deps[q->nb_buf_deps] = deps[i]; + if (!q->buf_deps[q->nb_buf_deps]) + goto err; + q->nb_buf_deps++; + } + + return 0; + +err: + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); +} + +FN_CREATING(FFVulkanContext, FFVkSampler, sampler, samplers, samplers_num) +FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, + int unnorm_coords, VkFilter filt) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkSamplerCreateInfo sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .magFilter = filt, + .minFilter = sampler_info.magFilter, + .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST : + VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = sampler_info.addressModeU, + .addressModeW = sampler_info.addressModeU, + .anisotropyEnable = VK_FALSE, + .compareOp = VK_COMPARE_OP_NEVER, + .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, + .unnormalizedCoordinates = unnorm_coords, + }; + + FFVkSampler *sctx = create_sampler(s); + if (!sctx) + return NULL; + + ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info, + s->hwctx->alloc, &sctx->sampler[0]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n", + ff_vk_ret2str(ret)); + return NULL; + } + + for (int i = 1; i < 4; i++) + sctx->sampler[i] = sctx->sampler[0]; + + return sctx; +} + +int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt) +{ + if (pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA || + pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_RGB24 || + pix_fmt == AV_PIX_FMT_BGR24 || pix_fmt == AV_PIX_FMT_RGB48 || + pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 || + pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0 || + pix_fmt == AV_PIX_FMT_0BGR || pix_fmt == AV_PIX_FMT_RGB0) + return 1; + return 0; +} + +const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixfmt); + const int high = desc->comp[0].depth > 8; + return high ? "rgba16f" : "rgba8"; +} + +typedef struct ImageViewCtx { + VkImageView view; +} ImageViewCtx; + +static void destroy_imageview(void *opaque, uint8_t *data) +{ + FFVulkanContext *s = opaque; + FFVulkanFunctions *vk = &s->vkfn; + ImageViewCtx *iv = (ImageViewCtx *)data; + + vk->DestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc); + av_free(iv); +} + +int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, + VkImageView *v, VkImage img, VkFormat fmt, + const VkComponentMapping map) +{ + int err; + AVBufferRef *buf; + FFVulkanFunctions *vk = &s->vkfn; + + VkImageViewCreateInfo imgview_spawn = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = NULL, + .image = img, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = fmt, + .components = map, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + ImageViewCtx *iv = av_mallocz(sizeof(*iv)); + + VkResult ret = vk->CreateImageView(s->hwctx->act_dev, &imgview_spawn, + s->hwctx->alloc, &iv->view); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0); + if (!buf) { + destroy_imageview(s, (uint8_t *)iv); + return AVERROR(ENOMEM); + } + + /* Add to queue dependencies */ + err = ff_vk_add_dep_exec_ctx(s, e, &buf, 1); + if (err) { + av_buffer_unref(&buf); + return err; + } + + *v = iv->view; + + return 0; +} + +FN_CREATING(FFVulkanPipeline, FFVkSPIRVShader, shader, shaders, shaders_num) +FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, + VkShaderStageFlags stage) +{ + FFVkSPIRVShader *shd = create_shader(pl); + if (!shd) + return NULL; + + av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED); + + shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shd->shader.stage = stage; + + shd->name = name; + + GLSLF(0, #version %i ,460); + GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) ); + GLSLC(0, ); + + return shd; +} + +void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]) +{ + shd->local_size[0] = local_size[0]; + shd->local_size[1] = local_size[1]; + shd->local_size[2] = local_size[2]; + + av_bprintf(&shd->src, "layout (local_size_x = %i, " + "local_size_y = %i, local_size_z = %i) in;\n\n", + shd->local_size[0], shd->local_size[1], shd->local_size[2]); +} + +void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio) +{ + int line = 0; + const char *p = shd->src.str; + const char *start = p; + + AVBPrint buf; + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + + for (int i = 0; i < strlen(p); i++) { + if (p[i] == '\n') { + av_bprintf(&buf, "%i\t", ++line); + av_bprint_append_data(&buf, start, &p[i] - start + 1); + start = &p[i + 1]; + } + } + + av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str); + av_bprint_finalize(&buf, NULL); +} + +int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, + const char *entrypoint) +{ +#if CONFIG_LIBGLSLANG + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkShaderModuleCreateInfo shader_create; + uint8_t *spirv; + size_t spirv_size; + void *priv; + + shd->shader.pName = entrypoint; + + err = ff_vk_glslang_shader_compile(s, shd, &spirv, &spirv_size, &priv); + if (err < 0) + return err; + + ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); + + av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", + shd->name, spirv_size); + + shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_create.pNext = NULL; + shader_create.codeSize = spirv_size; + shader_create.flags = 0; + shader_create.pCode = (void *)spirv; + + ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, + &shd->shader.module); + + ff_vk_glslang_shader_free(priv); + + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +#else + return AVERROR(ENOSYS); +#endif +} + +static const struct descriptor_props { + size_t struct_size; /* Size of the opaque which updates the descriptor */ + const char *type; + int is_uniform; + int mem_quali; /* Can use a memory qualifier */ + int dim_needed; /* Must indicate dimension */ + int buf_content; /* Must indicate buffer contents */ +} descriptor_props[] = { + [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, }, + [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, }, + [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, }, + [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, }, + [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, }, + [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, + [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, + [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, + [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, + [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, }, + [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, }, +}; + +int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, + int num, int only_print_to_shader) +{ + VkResult ret; + VkDescriptorSetLayout *layout; + FFVulkanFunctions *vk = &s->vkfn; + + if (only_print_to_shader) + goto print; + + pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout), + pl->desc_layout_num + pl->qf->nb_queues); + if (!pl->desc_layout) + return AVERROR(ENOMEM); + + pl->desc_set_initialized = av_realloc_array(pl->desc_set_initialized, + sizeof(*pl->desc_set_initialized), + pl->descriptor_sets_num + 1); + if (!pl->desc_set_initialized) + return AVERROR(ENOMEM); + + pl->desc_set_initialized[pl->descriptor_sets_num] = 0; + layout = &pl->desc_layout[pl->desc_layout_num]; + + { /* Create descriptor set layout descriptions */ + VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 }; + VkDescriptorSetLayoutBinding *desc_binding; + + desc_binding = av_mallocz(sizeof(*desc_binding)*num); + if (!desc_binding) + return AVERROR(ENOMEM); + + for (int i = 0; i < num; i++) { + desc_binding[i].binding = i; + desc_binding[i].descriptorType = desc[i].type; + desc_binding[i].descriptorCount = FFMAX(desc[i].elems, 1); + desc_binding[i].stageFlags = desc[i].stages; + desc_binding[i].pImmutableSamplers = desc[i].sampler ? + desc[i].sampler->sampler : + NULL; + } + + desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + desc_create_layout.pBindings = desc_binding; + desc_create_layout.bindingCount = num; + + for (int i = 0; i < pl->qf->nb_queues; i++) { + ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, + s->hwctx->alloc, &layout[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor set " + "layout: %s\n", ff_vk_ret2str(ret)); + av_free(desc_binding); + return AVERROR_EXTERNAL; + } + } + + av_free(desc_binding); + } + + { /* Pool each descriptor by type and update pool counts */ + for (int i = 0; i < num; i++) { + int j; + for (j = 0; j < pl->pool_size_desc_num; j++) + if (pl->pool_size_desc[j].type == desc[i].type) + break; + if (j >= pl->pool_size_desc_num) { + pl->pool_size_desc = av_realloc_array(pl->pool_size_desc, + sizeof(*pl->pool_size_desc), + ++pl->pool_size_desc_num); + if (!pl->pool_size_desc) + return AVERROR(ENOMEM); + memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize)); + } + pl->pool_size_desc[j].type = desc[i].type; + pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1)*pl->qf->nb_queues; + } + } + + { /* Create template creation struct */ + VkDescriptorUpdateTemplateCreateInfo *dt; + VkDescriptorUpdateTemplateEntry *des_entries; + + /* Freed after descriptor set initialization */ + des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry)); + if (!des_entries) + return AVERROR(ENOMEM); + + for (int i = 0; i < num; i++) { + des_entries[i].dstBinding = i; + des_entries[i].descriptorType = desc[i].type; + des_entries[i].descriptorCount = FFMAX(desc[i].elems, 1); + des_entries[i].dstArrayElement = 0; + des_entries[i].offset = ((uint8_t *)desc[i].updater) - (uint8_t *)s; + des_entries[i].stride = descriptor_props[desc[i].type].struct_size; + } + + pl->desc_template_info = av_realloc_array(pl->desc_template_info, + sizeof(*pl->desc_template_info), + pl->total_descriptor_sets + pl->qf->nb_queues); + if (!pl->desc_template_info) + return AVERROR(ENOMEM); + + dt = &pl->desc_template_info[pl->total_descriptor_sets]; + memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues); + + for (int i = 0; i < pl->qf->nb_queues; i++) { + dt[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; + dt[i].templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + dt[i].descriptorSetLayout = layout[i]; + dt[i].pDescriptorUpdateEntries = des_entries; + dt[i].descriptorUpdateEntryCount = num; + } + } + + pl->descriptor_sets_num++; + + pl->desc_layout_num += pl->qf->nb_queues; + pl->total_descriptor_sets += pl->qf->nb_queues; + +print: + /* Write shader info */ + for (int i = 0; i < num; i++) { + const struct descriptor_props *prop = &descriptor_props[desc[i].type]; + GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i); + + if (desc[i].mem_layout) + GLSLA(", %s", desc[i].mem_layout); + GLSLA(")"); + + if (prop->is_uniform) + GLSLA(" uniform"); + + if (prop->mem_quali && desc[i].mem_quali) + GLSLA(" %s", desc[i].mem_quali); + + if (prop->type) + GLSLA(" %s", prop->type); + + if (prop->dim_needed) + GLSLA("%iD", desc[i].dimensions); + + GLSLA(" %s", desc[i].name); + + if (prop->buf_content) + GLSLA(" {\n %s\n}", desc[i].buf_content); + else if (desc[i].elems > 0) + GLSLA("[%i]", desc[i].elems); + + GLSLA(";\n"); + } + GLSLA("\n"); + + return 0; +} + +void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + int set_id) +{ + FFVulkanFunctions *vk = &s->vkfn; + + /* If a set has never been updated, update all queues' sets. */ + if (!pl->desc_set_initialized[set_id]) { + for (int i = 0; i < pl->qf->nb_queues; i++) { + int idx = set_id*pl->qf->nb_queues + i; + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, + pl->desc_set[idx], + pl->desc_template[idx], + s); + } + pl->desc_set_initialized[set_id] = 1; + return; + } + + set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue; + + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, + pl->desc_set[set_id], + pl->desc_template[set_id], + s); +} + +void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, + VkShaderStageFlagBits stage, int offset, + size_t size, void *src) +{ + FFVulkanFunctions *vk = &s->vkfn; + + vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout, + stage, offset, size, src); +} + +int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + pl->desc_staging = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_staging)); + if (!pl->desc_staging) + return AVERROR(ENOMEM); + + { /* Init descriptor set pool */ + VkDescriptorPoolCreateInfo pool_create_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .poolSizeCount = pl->pool_size_desc_num, + .pPoolSizes = pl->pool_size_desc, + .maxSets = pl->total_descriptor_sets, + }; + + ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, + s->hwctx->alloc, &pl->desc_pool); + av_freep(&pl->pool_size_desc); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor set " + "pool: %s\n", ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + { /* Allocate descriptor sets */ + VkDescriptorSetAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = pl->desc_pool, + .descriptorSetCount = pl->total_descriptor_sets, + .pSetLayouts = pl->desc_layout, + }; + + pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set)); + if (!pl->desc_set) + return AVERROR(ENOMEM); + + ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &alloc_info, + pl->desc_set); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + { /* Finally create the pipeline layout */ + VkPipelineLayoutCreateInfo spawn_pipeline_layout = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pSetLayouts = (VkDescriptorSetLayout *)pl->desc_staging, + .pushConstantRangeCount = pl->push_consts_num, + .pPushConstantRanges = pl->push_consts, + }; + + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) + pl->desc_staging[spawn_pipeline_layout.setLayoutCount++] = pl->desc_layout[i]; + + ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, + s->hwctx->alloc, &pl->pipeline_layout); + av_freep(&pl->push_consts); + pl->push_consts_num = 0; + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + { /* Descriptor template (for tightly packed descriptors) */ + VkDescriptorUpdateTemplateCreateInfo *dt; + + pl->desc_template = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_template)); + if (!pl->desc_template) + return AVERROR(ENOMEM); + + /* Create update templates for the descriptor sets */ + for (int i = 0; i < pl->total_descriptor_sets; i++) { + dt = &pl->desc_template_info[i]; + dt->pipelineLayout = pl->pipeline_layout; + ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev, + dt, s->hwctx->alloc, + &pl->desc_template[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor " + "template: %s\n", ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + /* Free the duplicated memory used for the template entries */ + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { + dt = &pl->desc_template_info[i]; + av_free((void *)dt->pDescriptorUpdateEntries); + } + + av_freep(&pl->desc_template_info); + } + + return 0; +} + +FN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num) +FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf) +{ + FFVulkanPipeline *pl = create_pipeline(s); + if (pl) + pl->qf = qf; + + return pl; +} + +int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) +{ + int i; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkComputePipelineCreateInfo pipe = { + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .layout = pl->pipeline_layout, + }; + + for (i = 0; i < pl->shaders_num; i++) { + if (pl->shaders[i]->shader.stage & VK_SHADER_STAGE_COMPUTE_BIT) { + pipe.stage = pl->shaders[i]->shader; + break; + } + } + if (i == pl->shaders_num) { + av_log(s, AV_LOG_ERROR, "Can't init compute pipeline, no shader\n"); + return AVERROR(EINVAL); + } + + ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe, + s->hwctx->alloc, &pl->pipeline); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + + return 0; +} + +void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanPipeline *pl) +{ + FFVulkanFunctions *vk = &s->vkfn; + + vk->CmdBindPipeline(e->bufs[e->qf->cur_queue], pl->bind_point, pl->pipeline); + + for (int i = 0; i < pl->descriptor_sets_num; i++) + pl->desc_staging[i] = pl->desc_set[i*pl->qf->nb_queues + pl->qf->cur_queue]; + + vk->CmdBindDescriptorSets(e->bufs[e->qf->cur_queue], pl->bind_point, + pl->pipeline_layout, 0, + pl->descriptor_sets_num, + (VkDescriptorSet *)pl->desc_staging, + 0, NULL); + + e->bound_pl = pl; +} + +static void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) +{ + FFVulkanFunctions *vk = &s->vkfn; + + /* Make sure all queues have finished executing */ + for (int i = 0; i < e->qf->nb_queues; i++) { + FFVkQueueCtx *q = &e->queues[i]; + + if (q->fence) { + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); + } + + /* Free the fence */ + if (q->fence) + vk->DestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc); + + /* Free buffer dependencies */ + for (int j = 0; j < q->nb_buf_deps; j++) + av_buffer_unref(&q->buf_deps[j]); + av_free(q->buf_deps); + + /* Free frame dependencies */ + for (int j = 0; j < q->nb_frame_deps; j++) + av_frame_free(&q->frame_deps[j]); + av_free(q->frame_deps); + } + + if (e->bufs) + vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, e->qf->nb_queues, e->bufs); + if (e->pool) + vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); + + av_freep(&e->bufs); + av_freep(&e->queues); + av_freep(&e->sem_sig); + av_freep(&e->sem_sig_val); + av_freep(&e->sem_sig_val_dst); + av_freep(&e->sem_wait); + av_freep(&e->sem_wait_dst); + av_freep(&e->sem_wait_val); + av_free(e); +} + +static void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) +{ + FFVulkanFunctions *vk = &s->vkfn; + + for (int i = 0; i < pl->shaders_num; i++) { + FFVkSPIRVShader *shd = pl->shaders[i]; + av_bprint_finalize(&shd->src, NULL); + vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, + s->hwctx->alloc); + av_free(shd); + } + + vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); + vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout, + s->hwctx->alloc); + + for (int i = 0; i < pl->desc_layout_num; i++) { + if (pl->desc_template && pl->desc_template[i]) + vk->DestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i], + s->hwctx->alloc); + if (pl->desc_layout && pl->desc_layout[i]) + vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i], + s->hwctx->alloc); + } + + /* Also frees the descriptor sets */ + if (pl->desc_pool) + vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, + s->hwctx->alloc); + + av_freep(&pl->desc_staging); + av_freep(&pl->desc_set); + av_freep(&pl->shaders); + av_freep(&pl->desc_layout); + av_freep(&pl->desc_template); + av_freep(&pl->desc_set_initialized); + av_freep(&pl->push_consts); + pl->push_consts_num = 0; + + /* Only freed in case of failure */ + av_freep(&pl->pool_size_desc); + if (pl->desc_template_info) { + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { + VkDescriptorUpdateTemplateCreateInfo *dt = &pl->desc_template_info[i]; + av_free((void *)dt->pDescriptorUpdateEntries); + } + av_freep(&pl->desc_template_info); + } + + av_free(pl); +} + +void ff_vk_uninit(FFVulkanContext *s) +{ + FFVulkanFunctions *vk = &s->vkfn; + + ff_vk_glslang_uninit(); + + for (int i = 0; i < s->exec_ctx_num; i++) + free_exec_ctx(s, s->exec_ctx[i]); + av_freep(&s->exec_ctx); + + for (int i = 0; i < s->samplers_num; i++) { + vk->DestroySampler(s->hwctx->act_dev, s->samplers[i]->sampler[0], + s->hwctx->alloc); + av_free(s->samplers[i]); + } + av_freep(&s->samplers); + + for (int i = 0; i < s->pipelines_num; i++) + free_pipeline(s, s->pipelines[i]); + av_freep(&s->pipelines); + + av_freep(&s->scratch); + s->scratch_size = 0; + + av_buffer_unref(&s->device_ref); + av_buffer_unref(&s->frames_ref); +} diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h new file mode 100644 index 0000000000..14c69ce015 --- /dev/null +++ b/libavutil/vulkan.h @@ -0,0 +1,413 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_VULKAN_H +#define AVUTIL_VULKAN_H + +#define VK_NO_PROTOTYPES +#define VK_ENABLE_BETA_EXTENSIONS + +#include "pixdesc.h" +#include "bprint.h" +#include "hwcontext.h" +#include "hwcontext_vulkan.h" +#include "vulkan_functions.h" + +#define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ + VK_IMAGE_USAGE_STORAGE_BIT | \ + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \ + VK_IMAGE_USAGE_TRANSFER_DST_BIT) + +/* GLSL management macros */ +#define INDENT(N) INDENT_##N +#define INDENT_0 +#define INDENT_1 INDENT_0 " " +#define INDENT_2 INDENT_1 INDENT_1 +#define INDENT_3 INDENT_2 INDENT_1 +#define INDENT_4 INDENT_3 INDENT_1 +#define INDENT_5 INDENT_4 INDENT_1 +#define INDENT_6 INDENT_5 INDENT_1 +#define C(N, S) INDENT(N) #S "\n" +#define GLSLC(N, S) av_bprintf(&shd->src, C(N, S)) +#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__) +#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__) +#define GLSLD(D) GLSLC(0, ); \ + av_bprint_append_data(&shd->src, D, strlen(D)); \ + GLSLC(0, ) + +/* Helper, pretty much every Vulkan return value needs to be checked */ +#define RET(x) \ + do { \ + if ((err = (x)) < 0) \ + goto fail; \ + } while (0) + +typedef struct FFVkSPIRVShader { + const char *name; /* Name for id/debugging purposes */ + AVBPrint src; + int local_size[3]; /* Compute shader workgroup sizes */ + VkPipelineShaderStageCreateInfo shader; +} FFVkSPIRVShader; + +typedef struct FFVkSampler { + VkSampler sampler[4]; +} FFVkSampler; + +typedef struct FFVulkanDescriptorSetBinding { + const char *name; + VkDescriptorType type; + const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */ + const char *mem_quali; /* readonly, writeonly, etc. */ + const char *buf_content; /* For buffers */ + uint32_t dimensions; /* Needed for e.g. sampler%iD */ + uint32_t elems; /* 0 - scalar, 1 or more - vector */ + VkShaderStageFlags stages; + FFVkSampler *sampler; /* Sampler to use for all elems */ + void *updater; /* Pointer to VkDescriptor*Info */ +} FFVulkanDescriptorSetBinding; + +typedef struct FFVkBuffer { + VkBuffer buf; + VkDeviceMemory mem; + VkMemoryPropertyFlagBits flags; +} FFVkBuffer; + +typedef struct FFVkQueueFamilyCtx { + int queue_family; + int nb_queues; + int cur_queue; + int actual_queues; +} FFVkQueueFamilyCtx; + +typedef struct FFVulkanPipeline { + FFVkQueueFamilyCtx *qf; + + VkPipelineBindPoint bind_point; + + /* Contexts */ + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + + /* Shaders */ + FFVkSPIRVShader **shaders; + int shaders_num; + + /* Push consts */ + VkPushConstantRange *push_consts; + int push_consts_num; + + /* Descriptors */ + VkDescriptorSetLayout *desc_layout; + VkDescriptorPool desc_pool; + VkDescriptorSet *desc_set; + void **desc_staging; + VkDescriptorSetLayoutBinding **desc_binding; + VkDescriptorUpdateTemplate *desc_template; + int *desc_set_initialized; + int desc_layout_num; + int descriptor_sets_num; + int total_descriptor_sets; + int pool_size_desc_num; + + /* Temporary, used to store data in between initialization stages */ + VkDescriptorUpdateTemplateCreateInfo *desc_template_info; + VkDescriptorPoolSize *pool_size_desc; +} FFVulkanPipeline; + +typedef struct FFVkQueueCtx { + VkFence fence; + VkQueue queue; + + /* Buffer dependencies */ + AVBufferRef **buf_deps; + int nb_buf_deps; + int buf_deps_alloc_size; + + /* Frame dependencies */ + AVFrame **frame_deps; + int nb_frame_deps; + int frame_deps_alloc_size; +} FFVkQueueCtx; + +typedef struct FFVkExecContext { + FFVkQueueFamilyCtx *qf; + + VkCommandPool pool; + VkCommandBuffer *bufs; + FFVkQueueCtx *queues; + + AVBufferRef ***deps; + int *nb_deps; + int *dep_alloc_size; + + FFVulkanPipeline *bound_pl; + + VkSemaphore *sem_wait; + int sem_wait_alloc; /* Allocated sem_wait */ + int sem_wait_cnt; + + uint64_t *sem_wait_val; + int sem_wait_val_alloc; + + VkPipelineStageFlagBits *sem_wait_dst; + int sem_wait_dst_alloc; /* Allocated sem_wait_dst */ + + VkSemaphore *sem_sig; + int sem_sig_alloc; /* Allocated sem_sig */ + int sem_sig_cnt; + + uint64_t *sem_sig_val; + int sem_sig_val_alloc; + + uint64_t **sem_sig_val_dst; + int sem_sig_val_dst_alloc; +} FFVkExecContext; + +typedef struct FFVulkanContext { + const AVClass *class; /* Filters and encoders use this */ + + FFVulkanFunctions vkfn; + FFVulkanExtensions extensions; + VkPhysicalDeviceProperties props; + VkPhysicalDeviceMemoryProperties mprops; + + AVBufferRef *device_ref; + AVHWDeviceContext *device; + AVVulkanDeviceContext *hwctx; + + AVBufferRef *frames_ref; + AVHWFramesContext *frames; + AVVulkanFramesContext *hwfc; + + /* Properties */ + int output_width; + int output_height; + enum AVPixelFormat output_format; + enum AVPixelFormat input_format; + + /* Samplers */ + FFVkSampler **samplers; + int samplers_num; + + /* Exec contexts */ + FFVkExecContext **exec_ctx; + int exec_ctx_num; + + /* Pipelines (each can have 1 shader of each type) */ + FFVulkanPipeline **pipelines; + int pipelines_num; + + void *scratch; /* Scratch memory used only in functions */ + unsigned int scratch_size; +} FFVulkanContext; + +/* Identity mapping - r = r, b = b, g = g, a = a */ +extern const VkComponentMapping ff_comp_identity_map; + +/** + * Converts Vulkan return values to strings + */ +const char *ff_vk_ret2str(VkResult res); + +/** + * Returns 1 if the image is any sort of supported RGB + */ +int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); + +/** + * Gets the glsl format string for a pixel format + */ +const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); + +/** + * Initialize a queue family with a specific number of queues. + * If nb_queues == 0, use however many queues the queue family has. + */ +void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int nb_queues); + +/** + * Rotate through the queues in a queue family. + */ +void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf); + +/** + * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() + */ +FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords, + VkFilter filt); + +/** + * Create an imageview. + * Guaranteed to remain alive until the queue submission has finished executing, + * and will be destroyed after that. + */ +int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, + VkImageView *v, VkImage img, VkFormat fmt, + const VkComponentMapping map); + +/** + * Define a push constant for a given stage into a pipeline. + * Must be called before the pipeline layout has been initialized. + */ +int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, + VkShaderStageFlagBits stage); + +/** + * Inits a pipeline. Everything in it will be auto-freed when calling + * ff_vk_filter_uninit(). + */ +FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf); + +/** + * Inits a shader for a specific pipeline. Will be auto-freed on uninit. + */ +FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, + VkShaderStageFlags stage); + +/** + * Writes the workgroup size for a shader. + */ +void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]); + +/** + * Adds a descriptor set to the shader and registers them in the pipeline. + */ +int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, + int num, int only_print_to_shader); + +/** + * Compiles the shader, entrypoint must be set to "main". + */ +int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, + const char *entrypoint); + +/** + * Pretty print shader, mainly used by shader compilers. + */ +void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio); + +/** + * Initializes the pipeline layout after all shaders and descriptor sets have + * been finished. + */ +int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl); + +/** + * Initializes a compute pipeline. Will pick the first shader with the + * COMPUTE flag set. + */ +int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl); + +/** + * Updates a descriptor set via the updaters defined. + * Can be called immediately after pipeline creation, but must be called + * at least once before queue submission. + */ +void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + int set_id); + +/** + * Init an execution context for command recording and queue submission. + * WIll be auto-freed on uninit. + */ +int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, + FFVkQueueFamilyCtx *qf); + +/** + * Begin recording to the command buffer. Previous execution must have been + * completed, which ff_vk_submit_exec_queue() will ensure. + */ +int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e); + +/** + * Add a command to bind the completed pipeline and its descriptor sets. + * Must be called after ff_vk_start_exec_recording() and before submission. + */ +void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanPipeline *pl); + +/** + * Updates push constants. + * Must be called after binding a pipeline if any push constants were defined. + */ +void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, + VkShaderStageFlagBits stage, int offset, + size_t size, void *src); + +/** + * Gets the command buffer to use for this submission from the exe context. + */ +VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e); + +/** + * Adds a generic AVBufferRef as a queue depenency. + */ +int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, + AVBufferRef **deps, int nb_deps); + +/** + * Discards all queue dependencies + */ +void ff_vk_discard_exec_deps(FFVkExecContext *e); + +/** + * Adds a frame as a queue dependency. This also manages semaphore signalling. + * Must be called before submission. + */ +int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, + VkPipelineStageFlagBits in_wait_dst_flag); + +/** + * Submits a command buffer to the queue for execution. + * Will block until execution has finished in order to simplify resource + * management. + */ +int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e); + +/** + * Create a VkBuffer with the specified parameters. + */ +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); + +/** + * Maps the buffer to userspace. Set invalidate to 1 if reading the contents + * is necessary. + */ +int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], + int nb_buffers, int invalidate); + +/** + * Unmaps the buffer from userspace. Set flush to 1 to write and sync. + */ +int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, + int flush); + +/** + * Frees a buffer. + */ +void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf); + +/** + * Frees the main Vulkan context. + */ +void ff_vk_uninit(FFVulkanContext *s); + +#endif /* AVUTIL_VULKAN_H */ diff --git a/libavutil/vulkan_glslang.c b/libavutil/vulkan_glslang.c new file mode 100644 index 0000000000..51f76c9418 --- /dev/null +++ b/libavutil/vulkan_glslang.c @@ -0,0 +1,256 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "mem.h" +#include "avassert.h" + +#include "vulkan_glslang.h" + +static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; +static int glslang_refcount = 0; + +static const glslang_resource_t glslc_resource_limits = { + .max_lights = 32, + .max_clip_planes = 6, + .max_texture_units = 32, + .max_texture_coords = 32, + .max_vertex_attribs = 64, + .max_vertex_uniform_components = 4096, + .max_varying_floats = 64, + .max_vertex_texture_image_units = 32, + .max_combined_texture_image_units = 80, + .max_texture_image_units = 32, + .max_fragment_uniform_components = 4096, + .max_draw_buffers = 32, + .max_vertex_uniform_vectors = 128, + .max_varying_vectors = 8, + .max_fragment_uniform_vectors = 16, + .max_vertex_output_vectors = 16, + .max_fragment_input_vectors = 15, + .min_program_texel_offset = -8, + .max_program_texel_offset = 7, + .max_clip_distances = 8, + .max_compute_work_group_count_x = 65535, + .max_compute_work_group_count_y = 65535, + .max_compute_work_group_count_z = 65535, + .max_compute_work_group_size_x = 1024, + .max_compute_work_group_size_y = 1024, + .max_compute_work_group_size_z = 64, + .max_compute_uniform_components = 1024, + .max_compute_texture_image_units = 16, + .max_compute_image_uniforms = 8, + .max_compute_atomic_counters = 8, + .max_compute_atomic_counter_buffers = 1, + .max_varying_components = 60, + .max_vertex_output_components = 64, + .max_geometry_input_components = 64, + .max_geometry_output_components = 128, + .max_fragment_input_components = 128, + .max_image_units = 8, + .max_combined_image_units_and_fragment_outputs = 8, + .max_combined_shader_output_resources = 8, + .max_image_samples = 0, + .max_vertex_image_uniforms = 0, + .max_tess_control_image_uniforms = 0, + .max_tess_evaluation_image_uniforms = 0, + .max_geometry_image_uniforms = 0, + .max_fragment_image_uniforms = 8, + .max_combined_image_uniforms = 8, + .max_geometry_texture_image_units = 16, + .max_geometry_output_vertices = 256, + .max_geometry_total_output_components = 1024, + .max_geometry_uniform_components = 1024, + .max_geometry_varying_components = 64, + .max_tess_control_input_components = 128, + .max_tess_control_output_components = 128, + .max_tess_control_texture_image_units = 16, + .max_tess_control_uniform_components = 1024, + .max_tess_control_total_output_components = 4096, + .max_tess_evaluation_input_components = 128, + .max_tess_evaluation_output_components = 128, + .max_tess_evaluation_texture_image_units = 16, + .max_tess_evaluation_uniform_components = 1024, + .max_tess_patch_components = 120, + .max_patch_vertices = 32, + .max_tess_gen_level = 64, + .max_viewports = 16, + .max_vertex_atomic_counters = 0, + .max_tess_control_atomic_counters = 0, + .max_tess_evaluation_atomic_counters = 0, + .max_geometry_atomic_counters = 0, + .max_fragment_atomic_counters = 8, + .max_combined_atomic_counters = 8, + .max_atomic_counter_bindings = 1, + .max_vertex_atomic_counter_buffers = 0, + .max_tess_control_atomic_counter_buffers = 0, + .max_tess_evaluation_atomic_counter_buffers = 0, + .max_geometry_atomic_counter_buffers = 0, + .max_fragment_atomic_counter_buffers = 1, + .max_combined_atomic_counter_buffers = 1, + .max_atomic_counter_buffer_size = 16384, + .max_transform_feedback_buffers = 4, + .max_transform_feedback_interleaved_components = 64, + .max_cull_distances = 8, + .max_combined_clip_and_cull_distances = 8, + .max_samples = 4, + .max_mesh_output_vertices_nv = 256, + .max_mesh_output_primitives_nv = 512, + .max_mesh_work_group_size_x_nv = 32, + .max_mesh_work_group_size_y_nv = 1, + .max_mesh_work_group_size_z_nv = 1, + .max_task_work_group_size_x_nv = 32, + .max_task_work_group_size_y_nv = 1, + .max_task_work_group_size_z_nv = 1, + .max_mesh_view_count_nv = 4, + .maxDualSourceDrawBuffersEXT = 1, + + .limits = { + .non_inductive_for_loops = 1, + .while_loops = 1, + .do_while_loops = 1, + .general_uniform_indexing = 1, + .general_attribute_matrix_vector_indexing = 1, + .general_varying_indexing = 1, + .general_sampler_indexing = 1, + .general_variable_indexing = 1, + .general_constant_matrix_vector_indexing = 1, + } +}; + +int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, + uint8_t **data, size_t *size, void **opaque) +{ + const char *messages; + glslang_shader_t *glslc_shader; + glslang_program_t *glslc_program; + + static const glslang_stage_t glslc_stage[] = { + [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_STAGE_VERTEX, + [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT, + [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_STAGE_COMPUTE, + }; + + const glslang_input_t glslc_input = { + .language = GLSLANG_SOURCE_GLSL, + .stage = glslc_stage[shd->shader.stage], + .client = GLSLANG_CLIENT_VULKAN, + /* GLSLANG_TARGET_VULKAN_1_2 before 11.6 resulted in targeting 1.0 */ +#if (((GLSLANG_VERSION_MAJOR) > 11) || ((GLSLANG_VERSION_MAJOR) == 11 && \ + (((GLSLANG_VERSION_MINOR) > 6) || ((GLSLANG_VERSION_MINOR) == 6 && \ + ((GLSLANG_VERSION_PATCH) > 0))))) + .client_version = GLSLANG_TARGET_VULKAN_1_2, + .target_language_version = GLSLANG_TARGET_SPV_1_5, +#else + .client_version = GLSLANG_TARGET_VULKAN_1_1, + .target_language_version = GLSLANG_TARGET_SPV_1_3, +#endif + .target_language = GLSLANG_TARGET_SPV, + .code = shd->src.str, + .default_version = 460, + .default_profile = GLSLANG_NO_PROFILE, + .force_default_version_and_profile = false, + .forward_compatible = false, + .messages = GLSLANG_MSG_DEFAULT_BIT, + .resource = &glslc_resource_limits, + }; + + av_assert0(glslang_refcount); + + if (!(glslc_shader = glslang_shader_create(&glslc_input))) + return AVERROR(ENOMEM); + + if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!glslang_shader_parse(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!(glslc_program = glslang_program_create())) { + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_add_shader(glslc_program, glslc_shader); + + if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT | + GLSLANG_MSG_VULKAN_RULES_BIT)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n", + glslang_program_get_info_log(glslc_program), + glslang_program_get_info_debug_log(glslc_program)); + glslang_program_delete(glslc_program); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); + + messages = glslang_program_SPIRV_get_messages(glslc_program); + if (messages) + av_log(avctx, AV_LOG_WARNING, "%s\n", messages); + + glslang_shader_delete(glslc_shader); + + *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int); + *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program); + *opaque = glslc_program; + + return 0; +} + +void ff_vk_glslang_shader_free(void *opaque) +{ + glslang_program_delete(opaque); +} + +int ff_vk_glslang_init(void) +{ + int ret = 0; + + pthread_mutex_lock(&glslang_mutex); + if (glslang_refcount++ == 0) + ret = !glslang_initialize_process(); + pthread_mutex_unlock(&glslang_mutex); + + return ret; +} + +void ff_vk_glslang_uninit(void) +{ + pthread_mutex_lock(&glslang_mutex); + if (glslang_refcount && (--glslang_refcount == 0)) + glslang_finalize_process(); + pthread_mutex_unlock(&glslang_mutex); +} diff --git a/libavfilter/glslang.h b/libavutil/vulkan_glslang.h similarity index 87% rename from libavfilter/glslang.h rename to libavutil/vulkan_glslang.h index 93a077dbfc..b09d1251bf 100644 --- a/libavfilter/glslang.h +++ b/libavutil/vulkan_glslang.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVFILTER_GLSLANG_H -#define AVFILTER_GLSLANG_H +#ifndef AVUTIL_GLSLANG_H +#define AVUTIL_GLSLANG_H #include "vulkan.h" @@ -30,7 +30,7 @@ void ff_vk_glslang_uninit(void); /** * Compile GLSL into SPIR-V using glslang. */ -int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, +int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, uint8_t **data, size_t *size, void **opaque); /** @@ -38,4 +38,4 @@ int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, */ void ff_vk_glslang_shader_free(void *opaque); -#endif /* AVFILTER_GLSLANG_H */ +#endif /* AVUTIL_GLSLANG_H */ From b2aec70bd6bbf4620d363dfdc7d9e54f2f32f9ee Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 19 Nov 2021 12:07:10 +0100 Subject: [PATCH 200/894] lavu/vulkan: add option to switch between shader compilers and cleanup glslang --- libavfilter/Makefile | 2 -- libavfilter/glslang.c | 19 ---------- libavfilter/vulkan.c | 3 -- libavutil/vulkan.c | 33 ++++++++++------- libavutil/vulkan.h | 15 ++++++++ libavutil/vulkan_glslang.c | 72 +++++++++++++++++++++++++------------- libavutil/vulkan_glslang.h | 41 ---------------------- 7 files changed, 84 insertions(+), 101 deletions(-) delete mode 100644 libavfilter/glslang.c delete mode 100644 libavutil/vulkan_glslang.h diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 07b4a639ec..868ba68b79 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -578,8 +578,6 @@ SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h -OBJS-$(CONFIG_LIBGLSLANG) += glslang.o - TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral diff --git a/libavfilter/glslang.c b/libavfilter/glslang.c deleted file mode 100644 index 9aa41567a3..0000000000 --- a/libavfilter/glslang.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/vulkan_glslang.c" diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index e0fcf87f21..08e0c37cc4 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -188,8 +188,5 @@ int ff_vk_filter_init(AVFilterContext *avctx) s->output_format = AV_PIX_FMT_NONE; - if (ff_vk_glslang_init()) - return AVERROR_EXTERNAL; - return 0; } diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index fba9543cce..22f9bf7eb6 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -16,12 +16,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "vulkan.h" -#include "vulkan_glslang.h" - #include "avassert.h" + +#include "vulkan.h" #include "vulkan_loader.h" +#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG +#include "vulkan_glslang.c" +#endif + /* Generic macro for creating contexts which need to keep their addresses * if another context is created. */ #define FN_CREATING(ctx, type, shortname, array, num) \ @@ -843,7 +846,6 @@ void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio) int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, const char *entrypoint) { -#if CONFIG_LIBGLSLANG int err; VkResult ret; FFVulkanFunctions *vk = &s->vkfn; @@ -854,12 +856,21 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, shd->shader.pName = entrypoint; - err = ff_vk_glslang_shader_compile(s, shd, &spirv, &spirv_size, &priv); + if (!s->spirv_compiler) { +#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG + s->spirv_compiler = ff_vk_glslang_init(); +#else + return AVERROR(ENOSYS); +#endif + if (!s->spirv_compiler) + return AVERROR(ENOMEM); + } + + err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv, + &spirv_size, entrypoint, &priv); if (err < 0) return err; - ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); - av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", shd->name, spirv_size); @@ -872,7 +883,7 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, &shd->shader.module); - ff_vk_glslang_shader_free(priv); + s->spirv_compiler->free_shader(s->spirv_compiler, &priv); if (ret != VK_SUCCESS) { av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n", @@ -881,9 +892,6 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, } return 0; -#else - return AVERROR(ENOSYS); -#endif } static const struct descriptor_props { @@ -1367,7 +1375,8 @@ void ff_vk_uninit(FFVulkanContext *s) { FFVulkanFunctions *vk = &s->vkfn; - ff_vk_glslang_uninit(); + if (s->spirv_compiler) + s->spirv_compiler->uninit(&s->spirv_compiler); for (int i = 0; i < s->exec_ctx_num; i++) free_exec_ctx(s, s->exec_ctx[i]); diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 14c69ce015..3d89f02732 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -22,6 +22,10 @@ #define VK_NO_PROTOTYPES #define VK_ENABLE_BETA_EXTENSIONS +#ifndef FF_VK_ENABLE_SHADER_COMPILATION +#define FF_VK_ENABLE_SHADER_COMPILATION 1 +#endif + #include "pixdesc.h" #include "bprint.h" #include "hwcontext.h" @@ -64,6 +68,15 @@ typedef struct FFVkSPIRVShader { VkPipelineShaderStageCreateInfo shader; } FFVkSPIRVShader; +typedef struct FFVkSPIRVCompiler { + void *priv; + int (*compile_shader)(struct FFVkSPIRVCompiler *ctx, void *avctx, + struct FFVkSPIRVShader *shd, uint8_t **data, + size_t *size, const char *entrypoint, void **opaque); + void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque); + void (*uninit)(struct FFVkSPIRVCompiler **ctx); +} FFVkSPIRVCompiler; + typedef struct FFVkSampler { VkSampler sampler[4]; } FFVkSampler; @@ -194,6 +207,8 @@ typedef struct FFVulkanContext { AVHWFramesContext *frames; AVVulkanFramesContext *hwfc; + FFVkSPIRVCompiler *spirv_compiler; + /* Properties */ int output_width; int output_height; diff --git a/libavutil/vulkan_glslang.c b/libavutil/vulkan_glslang.c index 51f76c9418..ac5efe2365 100644 --- a/libavutil/vulkan_glslang.c +++ b/libavutil/vulkan_glslang.c @@ -24,10 +24,8 @@ #include "mem.h" #include "avassert.h" -#include "vulkan_glslang.h" - -static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; -static int glslang_refcount = 0; +static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER; +static int glslc_refcount = 0; static const glslang_resource_t glslc_resource_limits = { .max_lights = 32, @@ -137,8 +135,10 @@ static const glslang_resource_t glslc_resource_limits = { } }; -int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, - uint8_t **data, size_t *size, void **opaque) +static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, + FFVkSPIRVShader *shd, uint8_t **data, + size_t *size, const char *entrypoint, + void **opaque) { const char *messages; glslang_shader_t *glslc_shader; @@ -174,7 +174,7 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, .resource = &glslc_resource_limits, }; - av_assert0(glslang_refcount); + av_assert0(glslc_refcount); if (!(glslc_shader = glslang_shader_create(&glslc_input))) return AVERROR(ENOMEM); @@ -218,8 +218,12 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); messages = glslang_program_SPIRV_get_messages(glslc_program); - if (messages) + if (messages) { + ff_vk_print_shader(s, shd, AV_LOG_WARNING); av_log(avctx, AV_LOG_WARNING, "%s\n", messages); + } else { + ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); + } glslang_shader_delete(glslc_shader); @@ -230,27 +234,47 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, return 0; } -void ff_vk_glslang_shader_free(void *opaque) +static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque) { - glslang_program_delete(opaque); + if (!opaque || !*opaque) + return; + + av_assert0(glslc_refcount); + glslang_program_delete(*opaque); + *opaque = NULL; } -int ff_vk_glslang_init(void) +static void glslc_uninit(FFVkSPIRVCompiler **ctx) { - int ret = 0; + if (!ctx || !*ctx) + return; - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount++ == 0) - ret = !glslang_initialize_process(); - pthread_mutex_unlock(&glslang_mutex); + pthread_mutex_lock(&glslc_mutex); + if (glslc_refcount && (--glslc_refcount == 0)) + glslang_finalize_process(); + pthread_mutex_unlock(&glslc_mutex); + + av_freep(ctx); +} + +static FFVkSPIRVCompiler *ff_vk_glslang_init(void) +{ + FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); + if (!ret) + return NULL; + + ret->compile_shader = glslc_shader_compile; + ret->free_shader = glslc_shader_free; + ret->uninit = glslc_uninit; + + pthread_mutex_lock(&glslc_mutex); + if (!glslc_refcount++) { + if (!glslang_initialize_process()) { + av_freep(&ret); + glslc_refcount--; + } + } + pthread_mutex_unlock(&glslc_mutex); return ret; } - -void ff_vk_glslang_uninit(void) -{ - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount && (--glslang_refcount == 0)) - glslang_finalize_process(); - pthread_mutex_unlock(&glslang_mutex); -} diff --git a/libavutil/vulkan_glslang.h b/libavutil/vulkan_glslang.h deleted file mode 100644 index b09d1251bf..0000000000 --- a/libavutil/vulkan_glslang.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_GLSLANG_H -#define AVUTIL_GLSLANG_H - -#include "vulkan.h" - -/** - * Un/initialize glslang's global state. Thread-safe and reference counted. - */ -int ff_vk_glslang_init(void); -void ff_vk_glslang_uninit(void); - -/** - * Compile GLSL into SPIR-V using glslang. - */ -int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, - uint8_t **data, size_t *size, void **opaque); - -/** - * Frees the shader-specific context. - */ -void ff_vk_glslang_shader_free(void *opaque); - -#endif /* AVUTIL_GLSLANG_H */ From 67b92d68c68bc2fac682ca3671003913498bc44c Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 15 Nov 2021 23:15:38 -0300 Subject: [PATCH 201/894] x86/intmath: add VEX encoded versions of av_clipf() and av_clipd() Prevents mixing inlined SSE instructions and AVX instructions when the compiler generates the latter. Signed-off-by: James Almer --- libavutil/x86/intmath.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libavutil/x86/intmath.h b/libavutil/x86/intmath.h index 1520c25ec9..8a6b5ae261 100644 --- a/libavutil/x86/intmath.h +++ b/libavutil/x86/intmath.h @@ -134,6 +134,36 @@ static av_always_inline av_const float av_clipf_sse(float a, float amin, float a #endif /* __SSE__ */ +#if defined(__AVX__) && !defined(__INTEL_COMPILER) + +#undef av_clipd +#define av_clipd av_clipd_avx +static av_always_inline av_const double av_clipd_avx(double a, double amin, double amax) +{ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + __asm__ ("vmaxsd %1, %0, %0 \n\t" + "vminsd %2, %0, %0 \n\t" + : "+&x"(a) : "xm"(amin), "xm"(amax)); + return a; +} + +#undef av_clipf +#define av_clipf av_clipf_avx +static av_always_inline av_const float av_clipf_avx(float a, float amin, float amax) +{ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + __asm__ ("vmaxss %1, %0, %0 \n\t" + "vminss %2, %0, %0 \n\t" + : "+&x"(a) : "xm"(amin), "xm"(amax)); + return a; +} + +#endif /* __AVX__ */ + #endif /* __GNUC__ */ #endif /* AVUTIL_X86_INTMATH_H */ From ee3d6a20f6e11be23f3b75924d8a853b1af241f6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 14 Nov 2021 22:05:55 -0300 Subject: [PATCH 202/894] ffmpeg: Allocate (In|Out)putStream.filter_frame early Based on a commit by Andreas Rheinhardt. Signed-off-by: James Almer --- fftools/ffmpeg.c | 7 ------- fftools/ffmpeg_opt.c | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 7dfcfc13f5..5a0e95bf23 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1533,9 +1533,6 @@ static int reap_filters(int flush) if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_AUDIO) init_output_stream_wrapper(ost, NULL, 1); - if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { - return AVERROR(ENOMEM); - } filtered_frame = ost->filtered_frame; while (1) { @@ -2342,8 +2339,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) return AVERROR(ENOMEM); - if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) - return AVERROR(ENOMEM); decoded_frame = ist->decoded_frame; update_benchmark(NULL); @@ -2415,8 +2410,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) return AVERROR(ENOMEM); - if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) - return AVERROR(ENOMEM); decoded_frame = ist->decoded_frame; if (ist->dts != AV_NOPTS_VALUE) dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index b423d0e59c..f1fc4f742d 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -889,6 +889,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) exit_program(1); } + ist->filter_frame = av_frame_alloc(); + if (!ist->filter_frame) + exit_program(1); + ist->pkt = av_packet_alloc(); if (!ist->pkt) exit_program(1); @@ -1521,6 +1525,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e exit_program(1); } + ost->filtered_frame = av_frame_alloc(); + if (!ost->filtered_frame) + exit_program(1); + ost->pkt = av_packet_alloc(); if (!ost->pkt) exit_program(1); From e7f3279ba0ecd89eded5f91cb3bf5754761966db Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 14 Nov 2021 22:06:58 -0300 Subject: [PATCH 203/894] ffmpeg: Allocate InputStream.decoded_frame early Based on a commit by Andreas Rheinhardt. Signed-off-by: James Almer --- fftools/ffmpeg.c | 11 ++--------- fftools/ffmpeg_opt.c | 4 ++++ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5a0e95bf23..e88ca554ae 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2332,15 +2332,11 @@ static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, int *decode_failed) { - AVFrame *decoded_frame; + AVFrame *decoded_frame = ist->decoded_frame; AVCodecContext *avctx = ist->dec_ctx; int ret, err = 0; AVRational decoded_frame_tb; - if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - decoded_frame = ist->decoded_frame; - update_benchmark(NULL); ret = decode(avctx, decoded_frame, got_output, pkt); update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); @@ -2397,7 +2393,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *duration_pts, int eof, int *decode_failed) { - AVFrame *decoded_frame; + AVFrame *decoded_frame = ist->decoded_frame; int i, ret = 0, err = 0; int64_t best_effort_timestamp; int64_t dts = AV_NOPTS_VALUE; @@ -2408,9 +2404,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ if (!eof && pkt && pkt->size == 0) return 0; - if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - decoded_frame = ist->decoded_frame; if (ist->dts != AV_NOPTS_VALUE) dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); if (pkt) { diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index f1fc4f742d..98bd3b47b6 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -889,6 +889,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) exit_program(1); } + ist->decoded_frame = av_frame_alloc(); + if (!ist->decoded_frame) + exit_program(1); + ist->filter_frame = av_frame_alloc(); if (!ist->filter_frame) exit_program(1); From f6dd30df242cbf0a59c9ddfe66b23dc0ddaede66 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 19 Nov 2021 15:13:35 +0100 Subject: [PATCH 204/894] lavfi/vulkan: split off lavfi-specific code into vulkan_filter.c The issue is that libavfilter depends on libavcodec, and when doing a static build, if libavcodec also includes "libavfilter/vulkan.c", then during link-time, compiling programs will fail as there would be multiple definitions of the same symbols in both libavfilter and libavcodec's object files. Linkers are, however, more permitting if both files that include a common file that's used as a template are one-to-one identical. Hence, to make both files the same in the future, export all avfilter specific functions to a separate file. There is some work in progress to make templated files like this be compiled only once, so this is not a long-term solution. This also removes a macro that could be used to toggle SPIRV compilation capability on #include-time, as this could cause the files to be different. --- libavfilter/Makefile | 12 +- libavfilter/vf_avgblur_vulkan.c | 2 +- libavfilter/vf_chromaber_vulkan.c | 2 +- libavfilter/vf_gblur_vulkan.c | 2 +- libavfilter/vf_libplacebo.c | 2 +- libavfilter/vf_overlay_vulkan.c | 2 +- libavfilter/vf_scale_vulkan.c | 2 +- libavfilter/vulkan.c | 173 --------------------------- libavfilter/vulkan.h | 9 -- libavfilter/vulkan_filter.c | 191 ++++++++++++++++++++++++++++++ libavfilter/vulkan_filter.h | 34 ++++++ libavutil/vulkan.c | 4 +- libavutil/vulkan.h | 5 +- 13 files changed, 240 insertions(+), 200 deletions(-) create mode 100644 libavfilter/vulkan_filter.c create mode 100644 libavfilter/vulkan_filter.h diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 868ba68b79..56ffe44c3e 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -180,7 +180,7 @@ OBJS-$(CONFIG_ATADENOISE_FILTER) += vf_atadenoise.o OBJS-$(CONFIG_AVGBLUR_FILTER) += vf_avgblur.o OBJS-$(CONFIG_AVGBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ opencl/avgblur.o boxblur.o -OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER) += vf_avgblur_vulkan.o vulkan.o +OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER) += vf_avgblur_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_BBOX_FILTER) += bbox.o vf_bbox.o OBJS-$(CONFIG_BENCH_FILTER) += f_bench.o OBJS-$(CONFIG_BILATERAL_FILTER) += vf_bilateral.o @@ -194,7 +194,7 @@ OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ opencl/avgblur.o boxblur.o OBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o yadif_common.o OBJS-$(CONFIG_CAS_FILTER) += vf_cas.o -OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER) += vf_chromaber_vulkan.o vulkan.o +OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER) += vf_chromaber_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_CHROMAHOLD_FILTER) += vf_chromakey.o OBJS-$(CONFIG_CHROMAKEY_FILTER) += vf_chromakey.o OBJS-$(CONFIG_CHROMANR_FILTER) += vf_chromanr.o @@ -289,7 +289,7 @@ OBJS-$(CONFIG_FREEZEFRAMES_FILTER) += vf_freezeframes.o OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o OBJS-$(CONFIG_FSPP_FILTER) += vf_fspp.o qp_table.o OBJS-$(CONFIG_GBLUR_FILTER) += vf_gblur.o -OBJS-$(CONFIG_GBLUR_VULKAN_FILTER) += vf_gblur_vulkan.o vulkan.o +OBJS-$(CONFIG_GBLUR_VULKAN_FILTER) += vf_gblur_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_GEQ_FILTER) += vf_geq.o OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o OBJS-$(CONFIG_GRAPHMONITOR_FILTER) += f_graphmonitor.o @@ -324,7 +324,7 @@ OBJS-$(CONFIG_LAGFUN_FILTER) += vf_lagfun.o OBJS-$(CONFIG_LATENCY_FILTER) += f_latency.o OBJS-$(CONFIG_LENSCORRECTION_FILTER) += vf_lenscorrection.o OBJS-$(CONFIG_LENSFUN_FILTER) += vf_lensfun.o -OBJS-$(CONFIG_LIBPLACEBO_FILTER) += vf_libplacebo.o vulkan.o +OBJS-$(CONFIG_LIBPLACEBO_FILTER) += vf_libplacebo.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_LIBVMAF_FILTER) += vf_libvmaf.o framesync.o OBJS-$(CONFIG_LIMITDIFF_FILTER) += vf_limitdiff.o framesync.o OBJS-$(CONFIG_LIMITER_FILTER) += vf_limiter.o @@ -370,7 +370,7 @@ OBJS-$(CONFIG_OVERLAY_CUDA_FILTER) += vf_overlay_cuda.o framesync.o vf OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) += vf_overlay_opencl.o opencl.o \ opencl/overlay.o framesync.o OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o framesync.o -OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.o +OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PAD_OPENCL_FILTER) += vf_pad_opencl.o opencl.o opencl/pad.o @@ -415,7 +415,7 @@ OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \ OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o scale_eval.o OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o -OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o +OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o OBJS-$(CONFIG_SCALE2REF_NPP_FILTER) += vf_scale_npp.o scale_eval.o OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index d37d5a62b1..930f2a2bd9 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -18,7 +18,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #define CGS 32 diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 86a66454a4..03e493bc7f 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -18,7 +18,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #define CGROUPS (int [3]){ 32, 32, 1 } diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index 71d88d22e9..a2e33d1c90 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -19,7 +19,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #define CGS 32 diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index fe301db417..e2749857d1 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -19,7 +19,7 @@ #include "libavutil/file.h" #include "libavutil/opt.h" #include "internal.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "scale_eval.h" #include diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index ab97cf2c17..4308574f05 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -18,7 +18,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #include "framesync.h" diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index c2f6fe85e2..2eac901b1b 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -18,7 +18,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "scale_eval.h" #include "internal.h" #include "colorspace.h" diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index 08e0c37cc4..fc8a1fa47b 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -16,177 +16,4 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "vulkan.h" #include "libavutil/vulkan.c" - -static int vulkan_filter_set_device(AVFilterContext *avctx, - AVBufferRef *device) -{ - FFVulkanContext *s = avctx->priv; - - av_buffer_unref(&s->device_ref); - - s->device_ref = av_buffer_ref(device); - if (!s->device_ref) - return AVERROR(ENOMEM); - - s->device = (AVHWDeviceContext*)s->device_ref->data; - s->hwctx = s->device->hwctx; - - return 0; -} - -static int vulkan_filter_set_frames(AVFilterContext *avctx, - AVBufferRef *frames) -{ - FFVulkanContext *s = avctx->priv; - - av_buffer_unref(&s->frames_ref); - - s->frames_ref = av_buffer_ref(frames); - if (!s->frames_ref) - return AVERROR(ENOMEM); - - return 0; -} - -int ff_vk_filter_config_input(AVFilterLink *inlink) -{ - int err; - AVFilterContext *avctx = inlink->dst; - FFVulkanContext *s = avctx->priv; - FFVulkanFunctions *vk = &s->vkfn; - AVHWFramesContext *input_frames; - - if (!inlink->hw_frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " - "hardware frames context on the input.\n"); - return AVERROR(EINVAL); - } - - /* Extract the device and default output format from the first input. */ - if (avctx->inputs[0] != inlink) - return 0; - - input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data; - if (input_frames->format != AV_PIX_FMT_VULKAN) - return AVERROR(EINVAL); - - err = vulkan_filter_set_device(avctx, input_frames->device_ref); - if (err < 0) - return err; - err = vulkan_filter_set_frames(avctx, inlink->hw_frames_ctx); - if (err < 0) - return err; - - s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions, - s->hwctx->nb_enabled_dev_extensions); - - err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1); - if (err < 0) - return err; - - vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &s->props); - vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); - - /* Default output parameters match input parameters. */ - s->input_format = input_frames->sw_format; - if (s->output_format == AV_PIX_FMT_NONE) - s->output_format = input_frames->sw_format; - if (!s->output_width) - s->output_width = inlink->w; - if (!s->output_height) - s->output_height = inlink->h; - - return 0; -} - -int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) -{ - int err; - AVFilterContext *avctx = outlink->src; - FFVulkanContext *s = avctx->priv; - - av_buffer_unref(&outlink->hw_frames_ctx); - - if (!s->device_ref) { - if (!avctx->hw_device_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " - "Vulkan device.\n"); - return AVERROR(EINVAL); - } - - err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); - if (err < 0) - return err; - } - - outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref); - if (!outlink->hw_frames_ctx) - return AVERROR(ENOMEM); - - outlink->w = s->output_width; - outlink->h = s->output_height; - - return 0; -} - -int ff_vk_filter_config_output(AVFilterLink *outlink) -{ - int err; - AVFilterContext *avctx = outlink->src; - FFVulkanContext *s = avctx->priv; - AVBufferRef *output_frames_ref; - AVHWFramesContext *output_frames; - - av_buffer_unref(&outlink->hw_frames_ctx); - - if (!s->device_ref) { - if (!avctx->hw_device_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " - "Vulkan device.\n"); - return AVERROR(EINVAL); - } - - err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); - if (err < 0) - return err; - } - - output_frames_ref = av_hwframe_ctx_alloc(s->device_ref); - if (!output_frames_ref) { - err = AVERROR(ENOMEM); - goto fail; - } - output_frames = (AVHWFramesContext*)output_frames_ref->data; - - output_frames->format = AV_PIX_FMT_VULKAN; - output_frames->sw_format = s->output_format; - output_frames->width = s->output_width; - output_frames->height = s->output_height; - - err = av_hwframe_ctx_init(output_frames_ref); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to initialise output " - "frames: %d.\n", err); - goto fail; - } - - outlink->hw_frames_ctx = output_frames_ref; - outlink->w = s->output_width; - outlink->h = s->output_height; - - return 0; -fail: - av_buffer_unref(&output_frames_ref); - return err; -} - -int ff_vk_filter_init(AVFilterContext *avctx) -{ - FFVulkanContext *s = avctx->priv; - - s->output_format = AV_PIX_FMT_NONE; - - return 0; -} diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index 39c139cafa..928b2e21c3 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -19,15 +19,6 @@ #ifndef AVFILTER_VULKAN_H #define AVFILTER_VULKAN_H -#include "avfilter.h" #include "libavutil/vulkan.h" -/** - * General lavfi IO functions - */ -int ff_vk_filter_init (AVFilterContext *avctx); -int ff_vk_filter_config_input (AVFilterLink *inlink); -int ff_vk_filter_config_output (AVFilterLink *outlink); -int ff_vk_filter_config_output_inplace(AVFilterLink *outlink); - #endif /* AVFILTER_VULKAN_H */ diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c new file mode 100644 index 0000000000..e22541bd23 --- /dev/null +++ b/libavfilter/vulkan_filter.c @@ -0,0 +1,191 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vulkan_filter.h" + +static int vulkan_filter_set_device(AVFilterContext *avctx, + AVBufferRef *device) +{ + FFVulkanContext *s = avctx->priv; + + av_buffer_unref(&s->device_ref); + + s->device_ref = av_buffer_ref(device); + if (!s->device_ref) + return AVERROR(ENOMEM); + + s->device = (AVHWDeviceContext*)s->device_ref->data; + s->hwctx = s->device->hwctx; + + return 0; +} + +static int vulkan_filter_set_frames(AVFilterContext *avctx, + AVBufferRef *frames) +{ + FFVulkanContext *s = avctx->priv; + + av_buffer_unref(&s->frames_ref); + + s->frames_ref = av_buffer_ref(frames); + if (!s->frames_ref) + return AVERROR(ENOMEM); + + return 0; +} + +int ff_vk_filter_config_input(AVFilterLink *inlink) +{ + int err; + AVFilterContext *avctx = inlink->dst; + FFVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; + AVHWFramesContext *input_frames; + + if (!inlink->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + "hardware frames context on the input.\n"); + return AVERROR(EINVAL); + } + + /* Extract the device and default output format from the first input. */ + if (avctx->inputs[0] != inlink) + return 0; + + input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + if (input_frames->format != AV_PIX_FMT_VULKAN) + return AVERROR(EINVAL); + + err = vulkan_filter_set_device(avctx, input_frames->device_ref); + if (err < 0) + return err; + err = vulkan_filter_set_frames(avctx, inlink->hw_frames_ctx); + if (err < 0) + return err; + + s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions, + s->hwctx->nb_enabled_dev_extensions); + + err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1); + if (err < 0) + return err; + + vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &s->props); + vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); + + /* Default output parameters match input parameters. */ + s->input_format = input_frames->sw_format; + if (s->output_format == AV_PIX_FMT_NONE) + s->output_format = input_frames->sw_format; + if (!s->output_width) + s->output_width = inlink->w; + if (!s->output_height) + s->output_height = inlink->h; + + return 0; +} + +int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + FFVulkanContext *s = avctx->priv; + + av_buffer_unref(&outlink->hw_frames_ctx); + + if (!s->device_ref) { + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + "Vulkan device.\n"); + return AVERROR(EINVAL); + } + + err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); + if (err < 0) + return err; + } + + outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref); + if (!outlink->hw_frames_ctx) + return AVERROR(ENOMEM); + + outlink->w = s->output_width; + outlink->h = s->output_height; + + return 0; +} + +int ff_vk_filter_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + FFVulkanContext *s = avctx->priv; + AVBufferRef *output_frames_ref; + AVHWFramesContext *output_frames; + + av_buffer_unref(&outlink->hw_frames_ctx); + + if (!s->device_ref) { + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + "Vulkan device.\n"); + return AVERROR(EINVAL); + } + + err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); + if (err < 0) + return err; + } + + output_frames_ref = av_hwframe_ctx_alloc(s->device_ref); + if (!output_frames_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + output_frames = (AVHWFramesContext*)output_frames_ref->data; + + output_frames->format = AV_PIX_FMT_VULKAN; + output_frames->sw_format = s->output_format; + output_frames->width = s->output_width; + output_frames->height = s->output_height; + + err = av_hwframe_ctx_init(output_frames_ref); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise output " + "frames: %d.\n", err); + goto fail; + } + + outlink->hw_frames_ctx = output_frames_ref; + outlink->w = s->output_width; + outlink->h = s->output_height; + + return 0; +fail: + av_buffer_unref(&output_frames_ref); + return err; +} + +int ff_vk_filter_init(AVFilterContext *avctx) +{ + FFVulkanContext *s = avctx->priv; + + s->output_format = AV_PIX_FMT_NONE; + + return 0; +} diff --git a/libavfilter/vulkan_filter.h b/libavfilter/vulkan_filter.h new file mode 100644 index 0000000000..bfdb9b2d7d --- /dev/null +++ b/libavfilter/vulkan_filter.h @@ -0,0 +1,34 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_VULKAN_FILTER_H +#define AVFILTER_VULKAN_FILTER_H + +#include "avfilter.h" + +#include "vulkan.h" + +/** + * General lavfi IO functions + */ +int ff_vk_filter_init (AVFilterContext *avctx); +int ff_vk_filter_config_input (AVFilterLink *inlink); +int ff_vk_filter_config_output (AVFilterLink *outlink); +int ff_vk_filter_config_output_inplace(AVFilterLink *outlink); + +#endif /* AVFILTER_VULKAN_FILTER_H */ diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 22f9bf7eb6..3a70afe6a5 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -21,7 +21,7 @@ #include "vulkan.h" #include "vulkan_loader.h" -#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG +#if CONFIG_LIBGLSLANG #include "vulkan_glslang.c" #endif @@ -857,7 +857,7 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, shd->shader.pName = entrypoint; if (!s->spirv_compiler) { -#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG +#if CONFIG_LIBGLSLANG s->spirv_compiler = ff_vk_glslang_init(); #else return AVERROR(ENOSYS); diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 3d89f02732..9706fd5ccb 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -22,15 +22,12 @@ #define VK_NO_PROTOTYPES #define VK_ENABLE_BETA_EXTENSIONS -#ifndef FF_VK_ENABLE_SHADER_COMPILATION -#define FF_VK_ENABLE_SHADER_COMPILATION 1 -#endif - #include "pixdesc.h" #include "bprint.h" #include "hwcontext.h" #include "hwcontext_vulkan.h" #include "vulkan_functions.h" +#include "vulkan_loader.h" #define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ VK_IMAGE_USAGE_STORAGE_BIT | \ From 1d06084171604038ccae2d8a0a9c8fa99229ee52 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 19 Nov 2021 15:17:24 +0100 Subject: [PATCH 205/894] vulkan: fix checkheaders --- libavfilter/Makefile | 2 +- libavutil/Makefile | 4 +++- libavutil/vulkan.h | 5 +---- libavutil/vulkan_functions.h | 6 ++++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 56ffe44c3e..b94503a4ae 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -576,7 +576,7 @@ OBJS-$(CONFIG_SHARED) += log2_tab.o SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h -SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h +SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral diff --git a/libavutil/Makefile b/libavutil/Makefile index 410ac636f7..529046dbc8 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -205,7 +205,9 @@ SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h -SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h +SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \ + vulkan_functions.h \ + vulkan_loader.h TESTPROGS = adler32 \ aes \ diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 9706fd5ccb..d1ea1e24fb 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -19,14 +19,11 @@ #ifndef AVUTIL_VULKAN_H #define AVUTIL_VULKAN_H -#define VK_NO_PROTOTYPES -#define VK_ENABLE_BETA_EXTENSIONS - #include "pixdesc.h" #include "bprint.h" #include "hwcontext.h" -#include "hwcontext_vulkan.h" #include "vulkan_functions.h" +#include "hwcontext_vulkan.h" #include "vulkan_loader.h" #define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index f6881d8959..85a9f943c8 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -19,6 +19,12 @@ #ifndef AVUTIL_VULKAN_FUNCTIONS_H #define AVUTIL_VULKAN_FUNCTIONS_H +#define VK_NO_PROTOTYPES +#define VK_ENABLE_BETA_EXTENSIONS + +#include "hwcontext.h" +#include "hwcontext_vulkan.h" + /* An enum of bitflags for every optional extension we need */ typedef enum FFVulkanExtensions { FF_VK_EXT_EXTERNAL_DMABUF_MEMORY = 1ULL << 0, /* VK_EXT_external_memory_dma_buf */ From da72aca7b02503cdcdacd915dcf11929d29eecd1 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 19 Nov 2021 13:45:21 +0100 Subject: [PATCH 206/894] lavu/vulkan: add support for using libshaderc as a GLSL compiler It's got a much better API that's actually maintained, it eliminates race conditions, it comes with a pkg-config file by default, and unfortunately isn't currently packaged by Debian or other large distributions. --- configure | 21 ++++--- libavutil/vulkan.c | 4 ++ libavutil/vulkan_shaderc.c | 122 +++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 libavutil/vulkan_shaderc.c diff --git a/configure b/configure index 79252ac223..a5f5d15b04 100755 --- a/configure +++ b/configure @@ -262,6 +262,7 @@ External library support: --enable-librsvg enable SVG rasterization via librsvg [no] --enable-librubberband enable rubberband needed for rubberband filter [no] --enable-librtmp enable RTMP[E] support via librtmp [no] + --enable-libshaderc enable GLSL->SPIRV compilation via libshaderc [no] --enable-libshine enable fixed-point MP3 encoding via libshine [no] --enable-libsmbclient enable Samba protocol via libsmbclient [no] --enable-libsnappy enable Snappy compression, needed for hap encoding [no] @@ -1834,6 +1835,7 @@ EXTERNAL_LIBRARY_LIST=" librist librsvg librtmp + libshaderc libshine libsmbclient libsnappy @@ -3565,7 +3567,7 @@ ass_filter_deps="libass" atempo_filter_deps="avcodec" atempo_filter_select="rdft" avgblur_opencl_filter_deps="opencl" -avgblur_vulkan_filter_deps="vulkan libglslang" +avgblur_vulkan_filter_deps="vulkan spirv_compiler" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" bm3d_filter_deps="avcodec" @@ -3573,7 +3575,7 @@ bm3d_filter_select="dct" boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" -chromaber_vulkan_filter_deps="vulkan libglslang" +chromaber_vulkan_filter_deps="vulkan spirv_compiler" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" convolution_opencl_filter_deps="opencl" @@ -3613,7 +3615,7 @@ frei0r_deps_any="libdl LoadLibrary" frei0r_filter_deps="frei0r" frei0r_src_filter_deps="frei0r" fspp_filter_deps="gpl" -gblur_vulkan_filter_deps="vulkan libglslang" +gblur_vulkan_filter_deps="vulkan spirv_compiler" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" @@ -3638,7 +3640,7 @@ openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" -overlay_vulkan_filter_deps="vulkan libglslang" +overlay_vulkan_filter_deps="vulkan spirv_compiler" owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" @@ -3701,7 +3703,7 @@ zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" -scale_vulkan_filter_deps="vulkan libglslang" +scale_vulkan_filter_deps="vulkan spirv_compiler" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" xfade_opencl_filter_deps="opencl" @@ -6327,6 +6329,10 @@ if ! disabled ffnvcodec; then check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.11 ffnvcodec < 8.2" "$ffnv_hdr_list" "" fi +if enabled_all libglslang libshaderc; then + die "ERROR: libshaderc and libglslang are mutually exclusive, if in doubt, disable libglslang" +fi + check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" if ! disabled w32threads && ! enabled pthreads; then @@ -6443,10 +6449,10 @@ enabled fontconfig && enable libfontconfig enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info -enabled libglslang && { check_lib libglslang glslang/Include/glslang_c_interface.h glslang_initialize_process \ +enabled libglslang && { check_lib spirv_compiler glslang/Include/glslang_c_interface.h glslang_initialize_process \ -lglslang -lMachineIndependent -lOSDependent -lHLSL -lOGLCompiler -lGenericCodeGen \ -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm || - require libglslang glslang/Include/glslang_c_interface.h glslang_initialize_process \ + require spirv_compiler glslang/Include/glslang_c_interface.h glslang_initialize_process \ -lglslang -lOSDependent -lHLSL -lOGLCompiler \ -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm; } enabled libgme && { check_pkg_config libgme libgme gme/gme.h gme_new_emu || @@ -6504,6 +6510,7 @@ enabled librist && require_pkg_config librist "librist >= 0.2" librist enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++" +enabled libshaderc && require_pkg_config spirv_compiler "shaderc >= 2019.1" shaderc/shaderc.h shaderc_compiler_initialize enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer enabled libsmbclient && { check_pkg_config libsmbclient smbclient libsmbclient.h smbc_init || require libsmbclient libsmbclient.h smbc_init -lsmbclient; } diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 3a70afe6a5..a6463de622 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -23,6 +23,8 @@ #if CONFIG_LIBGLSLANG #include "vulkan_glslang.c" +#elif CONFIG_LIBSHADERC +#include "vulkan_shaderc.c" #endif /* Generic macro for creating contexts which need to keep their addresses @@ -859,6 +861,8 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, if (!s->spirv_compiler) { #if CONFIG_LIBGLSLANG s->spirv_compiler = ff_vk_glslang_init(); +#elif CONFIG_LIBSHADERC + s->spirv_compiler = ff_vk_shaderc_init(); #else return AVERROR(ENOSYS); #endif diff --git a/libavutil/vulkan_shaderc.c b/libavutil/vulkan_shaderc.c new file mode 100644 index 0000000000..bd40edf187 --- /dev/null +++ b/libavutil/vulkan_shaderc.c @@ -0,0 +1,122 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "mem.h" + +static int shdc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, + FFVkSPIRVShader *shd, uint8_t **data, + size_t *size, const char *entrypoint, + void **opaque) +{ + int loglevel, err, warn, ret; + const char *status, *message; + shaderc_compilation_result_t res; + static const char *shdc_result[] = { + [shaderc_compilation_status_success] = "success", + [shaderc_compilation_status_invalid_stage] = "invalid stage", + [shaderc_compilation_status_compilation_error] = "error", + [shaderc_compilation_status_internal_error] = "internal error", + [shaderc_compilation_status_null_result_object] = "no result", + [shaderc_compilation_status_invalid_assembly] = "invalid assembly", + }; + static const shaderc_shader_kind shdc_kind[] = { + [VK_SHADER_STAGE_VERTEX_BIT] = shaderc_glsl_vertex_shader, + [VK_SHADER_STAGE_FRAGMENT_BIT] = shaderc_glsl_fragment_shader, + [VK_SHADER_STAGE_COMPUTE_BIT] = shaderc_glsl_compute_shader, + }; + + shaderc_compile_options_t opts = shaderc_compile_options_initialize(); + if (!opts) + return AVERROR(ENOMEM); + + shaderc_compile_options_set_target_env(opts, shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_2); + shaderc_compile_options_set_target_spirv(opts, shaderc_spirv_version_1_5); + shaderc_compile_options_set_optimization_level(opts, + shaderc_optimization_level_performance); + + res = shaderc_compile_into_spv((shaderc_compiler_t)ctx->priv, + shd->src.str, strlen(shd->src.str), + shdc_kind[shd->shader.stage], + shd->name, entrypoint, opts); + shaderc_compile_options_release(opts); + + ret = shaderc_result_get_compilation_status(res); + err = shaderc_result_get_num_errors(res); + warn = shaderc_result_get_num_warnings(res); + message = shaderc_result_get_error_message(res); + + loglevel = err ? AV_LOG_ERROR : warn ? AV_LOG_WARNING : AV_LOG_VERBOSE; + + ff_vk_print_shader(avctx, shd, loglevel); + if (message && (err || warn)) + av_log(avctx, loglevel, "%s\n", message); + status = ret < FF_ARRAY_ELEMS(shdc_result) ? shdc_result[ret] : "unknown"; + av_log(avctx, loglevel, "shaderc compile status '%s' (%d errors, %d warnings)\n", + status, err, warn); + + if (err > 0) + return AVERROR(EINVAL); + + *data = (uint8_t *)shaderc_result_get_bytes(res); + *size = shaderc_result_get_length(res); + *opaque = res; + + return 0; +} + +static void shdc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque) +{ + if (!opaque || !*opaque) + return; + + shaderc_result_release((shaderc_compilation_result_t)*opaque); + *opaque = NULL; +} + +static void shdc_uninit(FFVkSPIRVCompiler **ctx) +{ + FFVkSPIRVCompiler *s; + + if (!ctx || !*ctx) + return; + + s = *ctx; + + shaderc_compiler_release((shaderc_compiler_t)s->priv); + av_freep(ctx); +} + +static FFVkSPIRVCompiler *ff_vk_shaderc_init(void) +{ + FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); + if (!ret) + return NULL; + + ret->compile_shader = shdc_shader_compile; + ret->free_shader = shdc_shader_free; + ret->uninit = shdc_uninit; + + ret->priv = (void *)shaderc_compiler_initialize(); + if (!ret->priv) + av_freep(&ret); + + return ret; +} From a1d1663458887e753d9321a02713ffac6af2659c Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:38 +0800 Subject: [PATCH 207/894] avfilter/avgblur_vulkan: check if shader is created with success Signed-off-by: Wu Jianhua --- libavfilter/vf_avgblur_vulkan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 930f2a2bd9..1161cb013e 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -111,6 +111,8 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) shd = ff_vk_init_shader(s->pl_hor, "avgblur_compute_hor", VK_SHADER_STAGE_COMPUTE_BIT); + if (!shd) + return AVERROR(ENOMEM); ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); @@ -154,6 +156,8 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) shd = ff_vk_init_shader(s->pl_ver, "avgblur_compute_ver", VK_SHADER_STAGE_COMPUTE_BIT); + if (!shd) + return AVERROR(ENOMEM); ff_vk_set_compute_shader_sizes(shd, (int [3]){ 1, CGS, 1 }); From 6a2284711eed19c247a55e0bdeab90e10a3e2ed1 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:39 +0800 Subject: [PATCH 208/894] avfilter/avgblur_vulkan: use FF_ARRAY_ELEMS instead of magic number Signed-off-by: Wu Jianhua --- libavfilter/vf_avgblur_vulkan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 1161cb013e..92c3a9aa7c 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -116,7 +116,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); - RET(ff_vk_add_descriptor_set(vkctx, s->pl_hor, shd, desc_i, 2, 0)); + RET(ff_vk_add_descriptor_set(vkctx, s->pl_hor, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_x - 1); GLSLC(0, #define INC(x) (ivec2(x, 0)) ); @@ -161,7 +161,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) ff_vk_set_compute_shader_sizes(shd, (int [3]){ 1, CGS, 1 }); - RET(ff_vk_add_descriptor_set(vkctx, s->pl_ver, shd, desc_i, 2, 0)); + RET(ff_vk_add_descriptor_set(vkctx, s->pl_ver, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_y - 1); GLSLC(0, #define INC(x) (ivec2(0, x)) ); From 766b1c170b8b5182d4f5036692195512c43e1d2b Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:40 +0800 Subject: [PATCH 209/894] avfilter/chromaber_vulkan: use FF_ARRAY_ELEMS instead of magic number Signed-off-by: Wu Jianhua --- libavfilter/vf_chromaber_vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 03e493bc7f..912ee8c609 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -126,7 +126,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) ff_vk_add_push_constant(s->pl, 0, sizeof(s->opts), VK_SHADER_STAGE_COMPUTE_BIT); - RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ GLSLD( distort_chroma_kernel ); GLSLC(0, void main() ); From 8763bdc8cfb080fa7aae0e02fed92ecd017d22d1 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:41 +0800 Subject: [PATCH 210/894] avfilter/scale_vulkan: use FF_ARRAY_ELEMS instead of magic number Signed-off-by: Wu Jianhua --- libavfilter/vf_scale_vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 2eac901b1b..33856fb8ad 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -179,7 +179,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) ff_vk_set_compute_shader_sizes(shd, CGROUPS); - RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( scale_bilinear ); From 14f78d6234f3c0370a7960c43792551b9533d314 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:42 +0800 Subject: [PATCH 211/894] avfilter/overlay_vulkan: use FF_ARRAY_ELEMS instead of magic number Signed-off-by: Wu Jianhua --- libavfilter/vf_overlay_vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 4308574f05..87bd6301ec 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -146,7 +146,7 @@ static av_cold int init_filter(AVFilterContext *ctx) ff_vk_set_compute_shader_sizes(shd, CGROUPS); - RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 3, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( overlay_noalpha ); From 9f2b204461015fed54ff114666679dcbee8a2b5e Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:43 +0800 Subject: [PATCH 212/894] avfilter/avgblur_vulkan: call av_vkfmt_from_pixfmt only one time Signed-off-by: Wu Jianhua --- libavfilter/vf_avgblur_vulkan.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 92c3a9aa7c..d118ce802c 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -212,6 +212,10 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; + + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + int planes = av_pix_fmt_count_planes(s->vkctx.output_format); /* Update descriptors and init the exec context */ @@ -221,17 +225,17 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f for (int i = 0; i < planes; i++) { RET(ff_vk_create_imageview(vkctx, s->exec, &s->input_images[i].imageView, in->img[i], - av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], + input_formats[i], ff_comp_identity_map)); RET(ff_vk_create_imageview(vkctx, s->exec, &s->tmp_images[i].imageView, tmp->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + output_formats[i], ff_comp_identity_map)); RET(ff_vk_create_imageview(vkctx, s->exec, &s->output_images[i].imageView, out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + output_formats[i], ff_comp_identity_map)); s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; From 6e4efe439f99fa512944bcacd8f2eaea28639196 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:44 +0800 Subject: [PATCH 213/894] avfilter/chromaber_vulkan: call av_vkfmt_from_pixfmt only one time Signed-off-by: Wu Jianhua --- libavfilter/vf_chromaber_vulkan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 912ee8c609..b9423e417e 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -180,6 +180,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *ouput_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); /* Update descriptors and init the exec context */ ff_vk_start_exec_recording(vkctx, s->exec); @@ -188,12 +190,12 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) for (int i = 0; i < planes; i++) { RET(ff_vk_create_imageview(vkctx, s->exec, &s->input_images[i].imageView, in->img[i], - av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], + input_formats[i], ff_comp_identity_map)); RET(ff_vk_create_imageview(vkctx, s->exec, &s->output_images[i].imageView, out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + ouput_formats[i], ff_comp_identity_map)); s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; From 404a58d5bee908a6340defccd99bb174106f854a Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:45 +0800 Subject: [PATCH 214/894] avfilter/scale_vulkan: call av_pix_fmt_count_planes only one time Signed-off-by: Wu Jianhua --- libavfilter/vf_scale_vulkan.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 33856fb8ad..414523418d 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -303,32 +303,30 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) AVVkFrame *out = (AVVkFrame *)out_f->data[0]; VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2]; int barrier_count = 0; + const int planes = av_pix_fmt_count_planes(s->vkctx.input_format); /* Update descriptors and init the exec context */ ff_vk_start_exec_recording(vkctx, s->exec); cmd_buf = ff_vk_get_exec_buf(s->exec); - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { + for (int i = 0; i < planes; i++) { RET(ff_vk_create_imageview(vkctx, s->exec, &s->input_images[i].imageView, in->img[i], av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], ff_comp_identity_map)); - s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.output_format); i++) { RET(ff_vk_create_imageview(vkctx, s->exec, &s->output_images[i].imageView, out->img[i], av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], ff_comp_identity_map)); + s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } ff_vk_update_descriptor_set(vkctx, s->pl, 0); - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { + for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = 0, From 067da5c87e73338da0944eaa6b4e1b0ff8ce3fd2 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:46 +0800 Subject: [PATCH 215/894] avfilter/scale_vulkan: call av_vkfmt_from_pixfmt only one time Signed-off-by: Wu Jianhua --- libavfilter/vf_scale_vulkan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 414523418d..cfce5ab1f8 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -304,6 +304,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2]; int barrier_count = 0; const int planes = av_pix_fmt_count_planes(s->vkctx.input_format); + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); /* Update descriptors and init the exec context */ ff_vk_start_exec_recording(vkctx, s->exec); @@ -312,12 +314,12 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) for (int i = 0; i < planes; i++) { RET(ff_vk_create_imageview(vkctx, s->exec, &s->input_images[i].imageView, in->img[i], - av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], + input_formats[i], ff_comp_identity_map)); RET(ff_vk_create_imageview(vkctx, s->exec, &s->output_images[i].imageView, out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + output_formats[i], ff_comp_identity_map)); s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; From 999048b6b18bd47a3415721376b5346a651bf785 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:47 +0800 Subject: [PATCH 216/894] avfilter/overlay_vulkan: call av_vkfmt_from_pixfmt only one time Signed-off-by: Wu Jianhua --- libavfilter/vf_overlay_vulkan.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 87bd6301ec..e87ee83000 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -242,9 +242,13 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVVkFrame *main = (AVVkFrame *)main_f->data[0]; AVVkFrame *overlay = (AVVkFrame *)overlay_f->data[0]; - AVHWFramesContext *main_fc = (AVHWFramesContext*)main_f->hw_frames_ctx->data; + AVHWFramesContext *main_fc = (AVHWFramesContext*)main_f->hw_frames_ctx->data; AVHWFramesContext *overlay_fc = (AVHWFramesContext*)overlay_f->hw_frames_ctx->data; + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + const VkFormat *main_sw_formats = av_vkfmt_from_pixfmt(main_fc->sw_format); + const VkFormat *overlay_sw_formats = av_vkfmt_from_pixfmt(overlay_fc->sw_format); + /* Update descriptors and init the exec context */ ff_vk_start_exec_recording(vkctx, s->exec); cmd_buf = ff_vk_get_exec_buf(s->exec); @@ -252,17 +256,17 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, for (int i = 0; i < planes; i++) { RET(ff_vk_create_imageview(vkctx, s->exec, &s->main_images[i].imageView, main->img[i], - av_vkfmt_from_pixfmt(main_fc->sw_format)[i], + main_sw_formats[i], ff_comp_identity_map)); RET(ff_vk_create_imageview(vkctx, s->exec, &s->overlay_images[i].imageView, overlay->img[i], - av_vkfmt_from_pixfmt(overlay_fc->sw_format)[i], + overlay_sw_formats[i], ff_comp_identity_map)); RET(ff_vk_create_imageview(vkctx, s->exec, &s->output_images[i].imageView, out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + output_formats[i], ff_comp_identity_map)); s->main_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; From ff82bd5a008e277e2120231d61a9d147b5b6312d Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 21:52:48 +0800 Subject: [PATCH 217/894] avutil/vulkan_glslang: fix compiling failure issue Signed-off-by: Wu Jianhua --- libavutil/vulkan_glslang.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/vulkan_glslang.c b/libavutil/vulkan_glslang.c index ac5efe2365..e7785f6d40 100644 --- a/libavutil/vulkan_glslang.c +++ b/libavutil/vulkan_glslang.c @@ -219,10 +219,10 @@ static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, messages = glslang_program_SPIRV_get_messages(glslc_program); if (messages) { - ff_vk_print_shader(s, shd, AV_LOG_WARNING); + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); av_log(avctx, AV_LOG_WARNING, "%s\n", messages); } else { - ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); + ff_vk_print_shader(avctx, shd, AV_LOG_VERBOSE); } glslang_shader_delete(glslc_shader); From d313cb5a2f62c4d75f554bca25833216dd637c9b Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 22:50:00 +0800 Subject: [PATCH 218/894] avfilter: add a hflip_vulkan filter The following command is on how to apply hflip_vulkan filter: ffmpeg -init_hw_device vulkan -i input.264 -vf hwupload=extra_hw_frames=16,hflip_vulkan,hwdownload,format=yuv420p output.264 Signed-off-by: Wu Jianhua --- configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_hflip_vulkan.c | 278 ++++++++++++++++++++++++++++++++++ 4 files changed, 281 insertions(+) create mode 100644 libavfilter/vf_hflip_vulkan.c diff --git a/configure b/configure index a5f5d15b04..37a738a0dd 100755 --- a/configure +++ b/configure @@ -3616,6 +3616,7 @@ frei0r_filter_deps="frei0r" frei0r_src_filter_deps="frei0r" fspp_filter_deps="gpl" gblur_vulkan_filter_deps="vulkan spirv_compiler" +hflip_vulkan_filter_deps="vulkan spirv_compiler" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index b94503a4ae..7ac29e2114 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -298,6 +298,7 @@ OBJS-$(CONFIG_GREYEDGE_FILTER) += vf_colorconstancy.o OBJS-$(CONFIG_GUIDED_FILTER) += vf_guided.o OBJS-$(CONFIG_HALDCLUT_FILTER) += vf_lut3d.o framesync.o OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o +OBJS-$(CONFIG_HFLIP_VULKAN_FILTER) += vf_hflip_vulkan.o vulkan.o OBJS-$(CONFIG_HISTEQ_FILTER) += vf_histeq.o OBJS-$(CONFIG_HISTOGRAM_FILTER) += vf_histogram.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 29da7ef0d2..82c50cba49 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -283,6 +283,7 @@ extern const AVFilter ff_vf_greyedge; extern const AVFilter ff_vf_guided; extern const AVFilter ff_vf_haldclut; extern const AVFilter ff_vf_hflip; +extern const AVFilter ff_vf_hflip_vulkan; extern const AVFilter ff_vf_histeq; extern const AVFilter ff_vf_histogram; extern const AVFilter ff_vf_hqdn3d; diff --git a/libavfilter/vf_hflip_vulkan.c b/libavfilter/vf_hflip_vulkan.c new file mode 100644 index 0000000000..b3a3d0b2aa --- /dev/null +++ b/libavfilter/vf_hflip_vulkan.c @@ -0,0 +1,278 @@ +/* + * copyright (c) 2021 Wu Jianhua + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/random_seed.h" +#include "libavutil/opt.h" +#include "vulkan_filter.h" +#include "internal.h" + +#define CGS 32 + +typedef struct HFlipVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl; + + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo output_images[3]; + + int initialized; +} HFlipVulkanContext; + +static av_cold int init_filter(AVFilterContext *avctx, AVFrame *in) +{ + int err = 0; + FFVkSPIRVShader *shd; + HFlipVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + FFVulkanDescriptorSetBinding image_descs[] = { + { + .name = "input_image", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->input_images, + }, + { + .name = "output_image", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->output_images, + }, + }; + + image_descs[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!image_descs[0].sampler) + return AVERROR_EXTERNAL; + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + { + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); + if (!s->pl) + return AVERROR(ENOMEM); + + shd = ff_vk_init_shader(s->pl, "hflip_compute", image_descs[0].stages); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_image[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i); + GLSLF(2, imageStore(output_image[%i], pos, res); ,i); + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(vkctx, shd, "main")); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); + } + + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + s->initialized = 1; + +fail: + return err; +} + +static av_cold void hflip_vulkan_uninit(AVFilterContext *avctx) +{ + HFlipVulkanContext *s = avctx->priv; + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe) +{ + int err = 0; + VkCommandBuffer cmd_buf; + HFlipVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &s->vkctx.vkfn; + AVVkFrame *in = (AVVkFrame *)inframe->data[0]; + AVVkFrame *out = (AVVkFrame *)outframe->data[0]; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); + + for (int i = 0; i < planes; i++) { + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], + input_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + output_formats[i], + ff_comp_identity_map)); + + s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + ff_vk_update_descriptor_set(vkctx, s->pl, 0); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = in->layout[i], + .newLayout = s->input_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = in->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, + .oldLayout = out->layout[i], + .newLayout = s->output_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = out->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + }; + + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers); + + in->layout[i] = barriers[0].newLayout; + in->access[i] = barriers[0].dstAccessMask; + + out->layout[i] = barriers[1].newLayout; + out->access[i] = barriers[1].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + s->vkctx.output_height, 1); + + ff_vk_add_exec_dep(vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + err = ff_vk_submit_exec_queue(vkctx, s->exec); + if (err) + return err; + + ff_vk_qf_rotate(&s->qf); + + return 0; +fail: + ff_vk_discard_exec_deps(s->exec); + return err; +} + +static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = link->dst; + HFlipVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) + RET(init_filter(ctx, in)); + + RET(process_frames(ctx, out, in)); + + RET(av_frame_copy_props(out, in)); + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static const AVOption hflip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(hflip_vulkan); + +static const AVFilterPad hflip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &hflip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +static const AVFilterPad hflip_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + } +}; + +const AVFilter ff_vf_hflip_vulkan = { + .name = "hflip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"), + .priv_size = sizeof(HFlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &hflip_vulkan_uninit, + FILTER_INPUTS(hflip_vulkan_inputs), + FILTER_OUTPUTS(hflip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &hflip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 3188b606d7ed74080e9d8c84a35430421184d043 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 19 Nov 2021 22:50:01 +0800 Subject: [PATCH 219/894] avfilter: add a vflip_vulkan filter The following command is on how to apply vflip_vulkan filter: ffmpeg -init_hw_device vulkan -i input.264 -vf hwupload=extra_hw_frames=16,vflip_vulkan,hwdownload,format=yuv420p output.264 Signed-off-by: Wu Jianhua --- configure | 1 + libavfilter/Makefile | 3 +- libavfilter/allfilters.c | 1 + .../{vf_hflip_vulkan.c => vf_flip_vulkan.c} | 106 +++++++++++++----- 4 files changed, 84 insertions(+), 27 deletions(-) rename libavfilter/{vf_hflip_vulkan.c => vf_flip_vulkan.c} (76%) diff --git a/configure b/configure index 37a738a0dd..d068b11073 100755 --- a/configure +++ b/configure @@ -3697,6 +3697,7 @@ transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" vaguedenoiser_filter_deps="gpl" +vflip_vulkan_filter_deps="vulkan spirv_compiler" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" libvmaf_filter_deps="libvmaf pthreads" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 7ac29e2114..0e27aeeff6 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -298,7 +298,7 @@ OBJS-$(CONFIG_GREYEDGE_FILTER) += vf_colorconstancy.o OBJS-$(CONFIG_GUIDED_FILTER) += vf_guided.o OBJS-$(CONFIG_HALDCLUT_FILTER) += vf_lut3d.o framesync.o OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o -OBJS-$(CONFIG_HFLIP_VULKAN_FILTER) += vf_hflip_vulkan.o vulkan.o +OBJS-$(CONFIG_HFLIP_VULKAN_FILTER) += vf_flip_vulkan.o vulkan.o OBJS-$(CONFIG_HISTEQ_FILTER) += vf_histeq.o OBJS-$(CONFIG_HISTOGRAM_FILTER) += vf_histogram.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o @@ -493,6 +493,7 @@ OBJS-$(CONFIG_VAGUEDENOISER_FILTER) += vf_vaguedenoiser.o OBJS-$(CONFIG_VARBLUR_FILTER) += vf_varblur.o framesync.o OBJS-$(CONFIG_VECTORSCOPE_FILTER) += vf_vectorscope.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o +OBJS-$(CONFIG_VFLIP_VULKAN_FILTER) += vf_flip_vulkan.o vulkan.o OBJS-$(CONFIG_VFRDET_FILTER) += vf_vfrdet.o OBJS-$(CONFIG_VIBRANCE_FILTER) += vf_vibrance.o OBJS-$(CONFIG_VIDSTABDETECT_FILTER) += vidstabutils.o vf_vidstabdetect.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 82c50cba49..4bf17ef292 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -470,6 +470,7 @@ extern const AVFilter ff_vf_vaguedenoiser; extern const AVFilter ff_vf_varblur; extern const AVFilter ff_vf_vectorscope; extern const AVFilter ff_vf_vflip; +extern const AVFilter ff_vf_vflip_vulkan; extern const AVFilter ff_vf_vfrdet; extern const AVFilter ff_vf_vibrance; extern const AVFilter ff_vf_vidstabdetect; diff --git a/libavfilter/vf_hflip_vulkan.c b/libavfilter/vf_flip_vulkan.c similarity index 76% rename from libavfilter/vf_hflip_vulkan.c rename to libavfilter/vf_flip_vulkan.c index b3a3d0b2aa..e9e04db91b 100644 --- a/libavfilter/vf_hflip_vulkan.c +++ b/libavfilter/vf_flip_vulkan.c @@ -24,7 +24,12 @@ #define CGS 32 -typedef struct HFlipVulkanContext { +enum FlipType { + FLIP_VERTICAL, + FLIP_HORIZONTAL +}; + +typedef struct FlipVulkanContext { FFVulkanContext vkctx; FFVkQueueFamilyCtx qf; FFVkExecContext *exec; @@ -34,13 +39,13 @@ typedef struct HFlipVulkanContext { VkDescriptorImageInfo output_images[3]; int initialized; -} HFlipVulkanContext; +} FlipVulkanContext; -static av_cold int init_filter(AVFilterContext *avctx, AVFrame *in) +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType type) { int err = 0; FFVkSPIRVShader *shd; - HFlipVulkanContext *s = avctx->priv; + FlipVulkanContext *s = ctx->priv; FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); @@ -76,26 +81,37 @@ static av_cold int init_filter(AVFilterContext *avctx, AVFrame *in) if (!s->pl) return AVERROR(ENOMEM); - shd = ff_vk_init_shader(s->pl, "hflip_compute", image_descs[0].stages); + shd = ff_vk_init_shader(s->pl, "flip_compute", image_descs[0].stages); if (!shd) return AVERROR(ENOMEM); ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 size; ); - GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); for (int i = 0; i < planes; i++) { - GLSLC(0, ); - GLSLF(1, size = imageSize(output_image[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i); - GLSLF(2, imageStore(output_image[%i], pos, res); ,i); - GLSLC(1, } ); + GLSLC(0, ); + GLSLF(1, size = imageSize(output_image[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + switch (type) + { + case FLIP_HORIZONTAL: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i); + break; + case FLIP_VERTICAL: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(pos.x, size.y - pos.y)); ,i); + break; + default: + GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); + break; + } + GLSLF(2, imageStore(output_image[%i], pos, res); ,i); + GLSLC(1, } ); } - GLSLC(0, } ); + GLSLC(0, } ); RET(ff_vk_compile_shader(vkctx, shd, "main")); RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); @@ -109,9 +125,9 @@ fail: return err; } -static av_cold void hflip_vulkan_uninit(AVFilterContext *avctx) +static av_cold void flip_vulkan_uninit(AVFilterContext *avctx) { - HFlipVulkanContext *s = avctx->priv; + FlipVulkanContext *s = avctx->priv; ff_vk_uninit(&s->vkctx); s->initialized = 0; @@ -121,7 +137,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in { int err = 0; VkCommandBuffer cmd_buf; - HFlipVulkanContext *s = avctx->priv; + FlipVulkanContext *s = avctx->priv; FFVulkanContext *vkctx = &s->vkctx; FFVulkanFunctions *vk = &s->vkctx.vkfn; AVVkFrame *in = (AVVkFrame *)inframe->data[0]; @@ -210,12 +226,12 @@ fail: return err; } -static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) { int err; AVFrame *out = NULL; AVFilterContext *ctx = link->dst; - HFlipVulkanContext *s = ctx->priv; + FlipVulkanContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -225,7 +241,7 @@ static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) } if (!s->initialized) - RET(init_filter(ctx, in)); + RET(init_filter(ctx, in, type)); RET(process_frames(ctx, out, in)); @@ -241,6 +257,16 @@ fail: return err; } +static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return flip_vulkan_filter_frame(link, in, FLIP_HORIZONTAL); +} + +static int vflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return flip_vulkan_filter_frame(link, in, FLIP_VERTICAL); +} + static const AVOption hflip_vulkan_options[] = { { NULL }, }; @@ -256,7 +282,7 @@ static const AVFilterPad hflip_vulkan_inputs[] = { } }; -static const AVFilterPad hflip_vulkan_outputs[] = { +static const AVFilterPad flip_vulkan_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, @@ -267,12 +293,40 @@ static const AVFilterPad hflip_vulkan_outputs[] = { const AVFilter ff_vf_hflip_vulkan = { .name = "hflip_vulkan", .description = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"), - .priv_size = sizeof(HFlipVulkanContext), + .priv_size = sizeof(FlipVulkanContext), .init = &ff_vk_filter_init, - .uninit = &hflip_vulkan_uninit, + .uninit = &flip_vulkan_uninit, FILTER_INPUTS(hflip_vulkan_inputs), - FILTER_OUTPUTS(hflip_vulkan_outputs), + FILTER_OUTPUTS(flip_vulkan_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &hflip_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; + +static const AVOption vflip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(vflip_vulkan); + +static const AVFilterPad vflip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &vflip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +const AVFilter ff_vf_vflip_vulkan = { + .name = "vflip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Vertically flip the input video in Vulkan"), + .priv_size = sizeof(FlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &flip_vulkan_uninit, + FILTER_INPUTS(vflip_vulkan_inputs), + FILTER_OUTPUTS(flip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &vflip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From c03e53aea7c73ea90c21eea712c50ba227f8d164 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 9 Oct 2021 16:13:32 +0200 Subject: [PATCH 220/894] avformat/mux: Store pointer to interleavement func in FFFormatContext It avoids branches lateron and will allow to easily avoid the overhead of the linked list currently in use in case there is only one stream. Signed-off-by: Andreas Rheinhardt --- libavformat/internal.h | 6 ++++++ libavformat/mux.c | 19 +++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 1f301dd17a..290e114506 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -81,6 +81,12 @@ typedef struct FFFormatContext { */ int nb_interleaved_streams; + /** + * The interleavement function in use. Always set for muxers. + */ + int (*interleave_packet)(struct AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + /** * This buffer is only needed when packets were already buffered but * not decoded, for example to get the codec parameters in MPEG diff --git a/libavformat/mux.c b/libavformat/mux.c index a6e1a08be0..884640611a 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -334,6 +334,9 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT) si->nb_interleaved_streams++; } + si->interleave_packet = of->interleave_packet; + if (!si->interleave_packet) + si->interleave_packet = ff_interleave_packet_per_dts; if (!s->priv_data && of->priv_data_size > 0) { s->priv_data = av_mallocz(of->priv_data_size); @@ -1054,19 +1057,6 @@ const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) return NULL; } -/** - * A wrapper around AVOutputFormat.interleave_packet. - * See its documentation for details. - */ -static int interleave_packet(AVFormatContext *s, AVPacket *pkt, - int flush, int has_packet) -{ - if (s->oformat->interleave_packet) { - return s->oformat->interleave_packet(s, pkt, flush, has_packet); - } else - return ff_interleave_packet_per_dts(s, pkt, flush, has_packet); -} - static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) { int ret; @@ -1089,8 +1079,9 @@ static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush, int has_packet) { + FFFormatContext *const si = ffformatcontext(s); for (;; ) { - int ret = interleave_packet(s, pkt, flush, has_packet); + int ret = si->interleave_packet(s, pkt, flush, has_packet); if (ret <= 0) return ret; From 52d13d54e139d23a841e7d7a5cd09dc8904b150a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 9 Oct 2021 16:27:03 +0200 Subject: [PATCH 221/894] avformat/mux: Avoid overhead of packet list in case of single streams Reviewed-by: Paul B Mahol Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavformat/internal.h | 7 +++++++ libavformat/mux.c | 10 +++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 290e114506..20e93d9267 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -759,6 +759,13 @@ int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb, int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, int flush, int has_packet); +/** + * Interleave packets directly in the order in which they arrive + * without any sort of buffering. + */ +int ff_interleave_packet_passthrough(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + void ff_free_stream(AVFormatContext *s, AVStream *st); unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id); diff --git a/libavformat/mux.c b/libavformat/mux.c index 884640611a..1389bcc003 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -336,7 +336,9 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } si->interleave_packet = of->interleave_packet; if (!si->interleave_packet) - si->interleave_packet = ff_interleave_packet_per_dts; + si->interleave_packet = si->nb_interleaved_streams > 1 ? + ff_interleave_packet_per_dts : + ff_interleave_packet_passthrough; if (!s->priv_data && of->priv_data_size > 0) { s->priv_data = av_mallocz(of->priv_data_size); @@ -1028,6 +1030,12 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } } +int ff_interleave_packet_passthrough(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) +{ + return has_packet; +} + int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset) { AVStream *st; From ce8f77a903e1108bde774d5e0e59d8cd24f18c46 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 9 Oct 2021 16:34:13 +0200 Subject: [PATCH 222/894] avformat/nullenc: Use ff_interleave_packet_passthrough() It avoids the overhead of the packet list; furthermore, using ff_interleave_packet_per_dts() is wrong for the null muxer anyway, because said muxer accepts packets without timestamps, which ff_interleave_packet_per_dts() can't handle. Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavformat/nullenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/nullenc.c b/libavformat/nullenc.c index 7354913726..d4769d5920 100644 --- a/libavformat/nullenc.c +++ b/libavformat/nullenc.c @@ -20,6 +20,7 @@ */ #include "avformat.h" +#include "internal.h" static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt) { @@ -33,4 +34,5 @@ const AVOutputFormat ff_null_muxer = { .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_packet = null_write_packet, .flags = AVFMT_VARIABLE_FPS | AVFMT_NOFILE | AVFMT_NOTIMESTAMPS, + .interleave_packet = ff_interleave_packet_passthrough, }; From 379f8b8ec6213789afc174d57c2751c52e66a8a7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 14 Nov 2021 12:23:31 -0300 Subject: [PATCH 223/894] ffmpeg: remove unused hwaccel_get_buffer function pointer As well as the custom get_buffer2() implementation which would become a redundant wrapper for avcodec_default_get_buffer2() after this Signed-off-by: James Almer --- fftools/ffmpeg.c | 11 ----------- fftools/ffmpeg.h | 1 - 2 files changed, 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e88ca554ae..5e3bfcdbbc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2926,16 +2926,6 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat return *p; } -static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags) -{ - InputStream *ist = s->opaque; - - if (ist->hwaccel_get_buffer && frame->format == ist->hwaccel_pix_fmt) - return ist->hwaccel_get_buffer(s, frame, flags); - - return avcodec_default_get_buffer2(s, frame, flags); -} - static int init_input_stream(int ist_index, char *error, int error_len) { int ret; @@ -2951,7 +2941,6 @@ static int init_input_stream(int ist_index, char *error, int error_len) ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; - ist->dec_ctx->get_buffer2 = get_buffer; #if LIBAVCODEC_VERSION_MAJOR < 60 FF_DISABLE_DEPRECATION_WARNINGS ist->dec_ctx->thread_safe_callbacks = 1; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 545ff1c8e7..f27878b196 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -378,7 +378,6 @@ typedef struct InputStream { /* hwaccel context */ void *hwaccel_ctx; void (*hwaccel_uninit)(AVCodecContext *s); - int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; enum AVPixelFormat hwaccel_retrieved_pix_fmt; From 405685dec76b4bce3ba96bb83b3fac57d847a2fa Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 14 Nov 2021 12:23:31 -0300 Subject: [PATCH 224/894] ffmpeg: remove unused hw_frames_ctx AVBufferRef from InputStream Signed-off-by: James Almer --- fftools/ffmpeg.c | 6 ------ fftools/ffmpeg.h | 1 - 2 files changed, 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5e3bfcdbbc..fa66aa1cf9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2913,12 +2913,6 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } } - if (ist->hw_frames_ctx) { - s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx); - if (!s->hw_frames_ctx) - return AV_PIX_FMT_NONE; - } - ist->hwaccel_pix_fmt = *p; break; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f27878b196..e86ab61047 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -381,7 +381,6 @@ typedef struct InputStream { int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; enum AVPixelFormat hwaccel_retrieved_pix_fmt; - AVBufferRef *hw_frames_ctx; /* stats */ // combined size of all the packets read From 4586de94a70a6becc075d59ff7e6374eeabdf65c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Nov 2021 15:14:51 +0100 Subject: [PATCH 225/894] avformat/mxfenc: Store locally whether DNXHD profile is interlaced MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is just a flag per supported CID. So there is no reason to use an avpriv function for this purpose. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mxfenc.c | 47 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 2f363917fc..2d788568ef 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -2035,29 +2035,30 @@ static int mxf_parse_prores_frame(AVFormatContext *s, AVStream *st, AVPacket *pk } static const struct { - int cid; + uint16_t cid; + uint8_t interlaced; UID codec_ul; } mxf_dnxhd_codec_uls[] = { - { 1235, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 } }, // 1080p 10bit HIGH - { 1237, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 } }, // 1080p 8bit MED - { 1238, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 } }, // 1080p 8bit HIGH - { 1241, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 } }, // 1080i 10bit HIGH - { 1242, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 } }, // 1080i 8bit MED - { 1243, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 } }, // 1080i 8bit HIGH - { 1244, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x0a,0x00,0x00 } }, // 1080i 8bit TR - { 1250, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 } }, // 720p 10bit - { 1251, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 } }, // 720p 8bit HIGH - { 1252, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 } }, // 720p 8bit MED - { 1253, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 } }, // 720p 8bit LOW - { 1256, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x16,0x00,0x00 } }, // 1080p 10bit 444 - { 1258, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x18,0x00,0x00 } }, // 720p 8bit TR - { 1259, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x19,0x00,0x00 } }, // 1080p 8bit TR - { 1260, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x1a,0x00,0x00 } }, // 1080i 8bit TR MBAFF - { 1270, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 } }, // DNXHR 444 - { 1271, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 } }, // DNXHR HQX - { 1272, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 } }, // DNXHR HQ - { 1273, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 } }, // DNXHR SQ - { 1274, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 } }, // DNXHR LB + { 1235, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 } }, // 1080p 10bit HIGH + { 1237, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 } }, // 1080p 8bit MED + { 1238, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 } }, // 1080p 8bit HIGH + { 1241, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 } }, // 1080i 10bit HIGH + { 1242, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 } }, // 1080i 8bit MED + { 1243, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 } }, // 1080i 8bit HIGH + { 1244, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x0a,0x00,0x00 } }, // 1080i 8bit TR + { 1250, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 } }, // 720p 10bit + { 1251, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 } }, // 720p 8bit HIGH + { 1252, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 } }, // 720p 8bit MED + { 1253, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 } }, // 720p 8bit LOW + { 1256, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x16,0x00,0x00 } }, // 1080p 10bit 444 + { 1258, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x18,0x00,0x00 } }, // 720p 8bit TR + { 1259, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x19,0x00,0x00 } }, // 1080p 8bit TR + { 1260, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x1a,0x00,0x00 } }, // 1080i 8bit TR MBAFF + { 1270, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 } }, // DNXHR 444 + { 1271, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 } }, // DNXHR HQX + { 1272, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 } }, // DNXHR HQ + { 1273, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 } }, // DNXHR SQ + { 1274, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 } }, // DNXHR LB }; static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) @@ -2076,6 +2077,7 @@ static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt for (i = 0; i < FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls); i++) { if (cid == mxf_dnxhd_codec_uls[i].cid) { sc->codec_ul = &mxf_dnxhd_codec_uls[i].codec_ul; + sc->interlaced = mxf_dnxhd_codec_uls[i].interlaced; break; } } @@ -2097,9 +2099,6 @@ static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt if (frame_size < 0) return 0; - if ((sc->interlaced = avpriv_dnxhd_get_interlaced(cid)) < 0) - return 0; - if (cid >= 1270) { // RI raster av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, st->codecpar->width, st->codecpar->height, From 6a3df0dfa938e104c31576a9508c9a2cc8488f68 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Nov 2021 15:24:06 +0100 Subject: [PATCH 226/894] avcodec/dnxhddata: Remove avpriv_dnxhd_get_interlaced() It is unused. Signed-off-by: Andreas Rheinhardt --- libavcodec/dnxhddata.c | 8 -------- libavcodec/dnxhddata.h | 1 - 2 files changed, 9 deletions(-) diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index 3a69a0f501..e3b260f328 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -1105,14 +1105,6 @@ int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h) return FFMAX(result, 8192); } -int avpriv_dnxhd_get_interlaced(int cid) -{ - const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); - if (!entry) - return -1; - return entry->flags & DNXHD_INTERLACED ? 1 : 0; -} - static int dnxhd_find_hr_cid(AVCodecContext *avctx) { switch (avctx->profile) { diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index 898079cffc..ecb1cd0b2d 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -90,6 +90,5 @@ static av_always_inline uint64_t ff_dnxhd_parse_header_prefix(const uint8_t *buf int avpriv_dnxhd_get_frame_size(int cid); int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h); -int avpriv_dnxhd_get_interlaced(int cid); #endif /* AVCODEC_DNXHDDATA_H */ From b9a26b9d55f77ebbff3596e46be54bb5fed469d3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Nov 2021 14:51:14 +0100 Subject: [PATCH 227/894] avformat/mxfenc: Remove redundant DNXHD frame size checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The actual frame_size is no longer used since commit 3d38e45eb85c7a2420cb48a9cd45625c28644b2e; and the check for "< 0" is equivalent to the CID being valid. But this is already checked by avpriv_dnxhd_get_interlaced() (and is actually already ensured by mxf_dnxhd_codec_uls containing this CID). Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mxfenc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 2d788568ef..fcd9afda2a 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -2065,7 +2065,7 @@ static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt { MXFContext *mxf = s->priv_data; MXFStreamContext *sc = st->priv_data; - int i, cid, frame_size = 0; + int i, cid; if (mxf->header_written) return 1; @@ -2093,12 +2093,6 @@ static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt if (!sc->component_depth) return 0; - if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) == DNXHD_VARIABLE) { - frame_size = avpriv_dnxhd_get_hr_frame_size(cid, st->codecpar->width, st->codecpar->height); - } - if (frame_size < 0) - return 0; - if (cid >= 1270) { // RI raster av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, st->codecpar->width, st->codecpar->height, From 17c8533745305bdf9c26c87dcbc43453ed6f0804 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Nov 2021 15:35:22 +0100 Subject: [PATCH 228/894] avcodec/dnxhddata: Unavpriv dnxhd_get_(hr_|)_frame_size() It is no longer used in libavformat. Signed-off-by: Andreas Rheinhardt --- libavcodec/dnxhd_parser.c | 4 ++-- libavcodec/dnxhddata.c | 4 ++-- libavcodec/dnxhddata.h | 4 ++-- libavcodec/dnxhdenc.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/dnxhd_parser.c b/libavcodec/dnxhd_parser.c index 4ba619c9bb..631ac83860 100644 --- a/libavcodec/dnxhd_parser.c +++ b/libavcodec/dnxhd_parser.c @@ -73,9 +73,9 @@ static int dnxhd_find_frame_end(DNXHDParserContext *dctx, if (cid <= 0) continue; - remaining = avpriv_dnxhd_get_frame_size(cid); + remaining = ff_dnxhd_get_frame_size(cid); if (remaining <= 0) { - remaining = avpriv_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h); + remaining = ff_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h); if (remaining <= 0) continue; } diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index e3b260f328..cb3d4a4c72 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -1083,7 +1083,7 @@ const CIDEntry *ff_dnxhd_get_cid_table(int cid) return NULL; } -int avpriv_dnxhd_get_frame_size(int cid) +int ff_dnxhd_get_frame_size(int cid) { const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); if (!entry) @@ -1091,7 +1091,7 @@ int avpriv_dnxhd_get_frame_size(int cid) return entry->frame_size; } -int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h) +int ff_dnxhd_get_hr_frame_size(int cid, int w, int h) { const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); int result; diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index ecb1cd0b2d..861faca4ca 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -88,7 +88,7 @@ static av_always_inline uint64_t ff_dnxhd_parse_header_prefix(const uint8_t *buf return ff_dnxhd_check_header_prefix(prefix); } -int avpriv_dnxhd_get_frame_size(int cid); -int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h); +int ff_dnxhd_get_frame_size(int cid); +int ff_dnxhd_get_hr_frame_size(int cid, int w, int h); #endif /* AVCODEC_DNXHDDATA_H */ diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index ebfb85341d..ca67964330 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -463,7 +463,7 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width; if (ctx->cid_table->frame_size == DNXHD_VARIABLE) { - ctx->frame_size = avpriv_dnxhd_get_hr_frame_size(ctx->cid, + ctx->frame_size = ff_dnxhd_get_hr_frame_size(ctx->cid, avctx->width, avctx->height); av_assert0(ctx->frame_size >= 0); ctx->coding_unit_size = ctx->frame_size; From 53c8b16c19bfda815ec7bcad3ad3c5548b53d8d5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 07:19:58 +0100 Subject: [PATCH 229/894] avformat/utils: Remove duplicated AV_DISPOSITION_FOO <-> "foo" table Instead reuse stream_options. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavformat/utils.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 6eac3f721e..7840e8717c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1985,34 +1985,17 @@ void ff_format_set_url(AVFormatContext *s, char *url) s->url = url; } -static const struct { - const char *str; - int disposition; -} dispositions[] = { - { "default", AV_DISPOSITION_DEFAULT }, - { "dub", AV_DISPOSITION_DUB }, - { "original", AV_DISPOSITION_ORIGINAL }, - { "comment", AV_DISPOSITION_COMMENT }, - { "lyrics", AV_DISPOSITION_LYRICS }, - { "karaoke", AV_DISPOSITION_KARAOKE }, - { "forced", AV_DISPOSITION_FORCED }, - { "hearing_impaired", AV_DISPOSITION_HEARING_IMPAIRED }, - { "visual_impaired", AV_DISPOSITION_VISUAL_IMPAIRED }, - { "clean_effects", AV_DISPOSITION_CLEAN_EFFECTS }, - { "attached_pic", AV_DISPOSITION_ATTACHED_PIC }, - { "timed_thumbnails", AV_DISPOSITION_TIMED_THUMBNAILS }, - { "captions", AV_DISPOSITION_CAPTIONS }, - { "descriptions", AV_DISPOSITION_DESCRIPTIONS }, - { "metadata", AV_DISPOSITION_METADATA }, - { "dependent", AV_DISPOSITION_DEPENDENT }, - { "still_image", AV_DISPOSITION_STILL_IMAGE }, -}; +static int option_is_disposition(const AVOption *opt) +{ + return opt->type == AV_OPT_TYPE_CONST && + opt->unit && !strcmp(opt->unit, "disposition"); +} int av_disposition_from_string(const char *disp) { - for (int i = 0; i < FF_ARRAY_ELEMS(dispositions); i++) - if (!strcmp(disp, dispositions[i].str)) - return dispositions[i].disposition; + for (const AVOption *opt = stream_options; opt->name; opt++) + if (option_is_disposition(opt) && !strcmp(disp, opt->name)) + return opt->default_val.i64; return AVERROR(EINVAL); } @@ -2024,9 +2007,9 @@ const char *av_disposition_to_string(int disposition) return NULL; val = 1 << ff_ctz(disposition); - for (int i = 0; i < FF_ARRAY_ELEMS(dispositions); i++) - if (dispositions[i].disposition == val) - return dispositions[i].str; + for (const AVOption *opt = stream_options; opt->name; opt++) + if (option_is_disposition(opt) && opt->default_val.i64 == val) + return opt->name; return NULL; } From 01923579f477ede876c1611844efa970aa928392 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 07:26:21 +0100 Subject: [PATCH 230/894] avfilter/vf_huesaturation: Remove dead store Fixes Coverity issue #1493345. Reviewed-by: Steven Liu Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_huesaturation.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavfilter/vf_huesaturation.c b/libavfilter/vf_huesaturation.c index af7ea33b9e..d4e3fea1c5 100644 --- a/libavfilter/vf_huesaturation.c +++ b/libavfilter/vf_huesaturation.c @@ -297,7 +297,6 @@ static void transform_point(float matrix[4][4], float *tx, float *ty, float *tz) { x = y; - *tx = x; *tx = x * matrix[0][0] + y * matrix[1][0] + z * matrix[2][0] + matrix[3][0]; *ty = x * matrix[0][1] + y * matrix[1][1] + z * matrix[2][1] + matrix[3][1]; *tz = x * matrix[0][2] + y * matrix[1][2] + z * matrix[2][2] + matrix[3][2]; From a132614bba247afac30d3a8b1378c40bd7f672bc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 19 Nov 2021 17:29:33 +0100 Subject: [PATCH 231/894] fftools/ffmpeg: Avoid temporary frame send_frame_to_filters() sends a frame to all the filters that need said frame; for every filter except the last one this involves creating a reference to the frame, because av_buffersrc_add_frame_flags() by default takes ownership of the supplied references. Yet said function has a flag which changes its behaviour to create a reference itself. This commit uses this flag and stops creating the references itself; this allows to remove the spare AVFrame holding the temporary references; it also avoids unreferencing said frame. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 22 +++++++--------------- fftools/ffmpeg.h | 1 - fftools/ffmpeg_opt.c | 4 ---- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index fa66aa1cf9..c9a9cdfcd6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -633,7 +633,6 @@ static void ffmpeg_cleanup(int ret) InputStream *ist = input_streams[i]; av_frame_free(&ist->decoded_frame); - av_frame_free(&ist->filter_frame); av_packet_free(&ist->pkt); av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); @@ -2171,11 +2170,15 @@ static int ifilter_has_all_input_formats(FilterGraph *fg) return 1; } -static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) { FilterGraph *fg = ifilter->graph; AVFrameSideData *sd; int need_reinit, ret; + int buffersrc_flags = AV_BUFFERSRC_FLAG_PUSH; + + if (keep_reference) + buffersrc_flags |= AV_BUFFERSRC_FLAG_KEEP_REF; /* determine if the parameters for this input changed */ need_reinit = ifilter->format != frame->format; @@ -2217,7 +2220,6 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) AVFrame *tmp = av_frame_clone(frame); if (!tmp) return AVERROR(ENOMEM); - av_frame_unref(frame); if (!av_fifo_space(ifilter->frame_queue)) { ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); @@ -2243,7 +2245,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) } } - ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, AV_BUFFERSRC_FLAG_PUSH); + ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, buffersrc_flags); if (ret < 0) { if (ret != AVERROR_EOF) av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); @@ -2306,18 +2308,10 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacke static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) { int i, ret; - AVFrame *f; av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */ for (i = 0; i < ist->nb_filters; i++) { - if (i < ist->nb_filters - 1) { - f = ist->filter_frame; - ret = av_frame_ref(f, decoded_frame); - if (ret < 0) - break; - } else - f = decoded_frame; - ret = ifilter_send_frame(ist->filters[i], f); + ret = ifilter_send_frame(ist->filters[i], decoded_frame, i < ist->nb_filters - 1); if (ret == AVERROR_EOF) ret = 0; /* ignore */ if (ret < 0) { @@ -2385,7 +2379,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, ist->nb_samples = decoded_frame->nb_samples; err = send_frame_to_filters(ist, decoded_frame); - av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } @@ -2511,7 +2504,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ err = send_frame_to_filters(ist, decoded_frame); fail: - av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e86ab61047..1728010f56 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -311,7 +311,6 @@ typedef struct InputStream { AVCodecContext *dec_ctx; const AVCodec *dec; AVFrame *decoded_frame; - AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ AVPacket *pkt; int64_t prev_pkt_pts; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 98bd3b47b6..6732a29625 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -893,10 +893,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) if (!ist->decoded_frame) exit_program(1); - ist->filter_frame = av_frame_alloc(); - if (!ist->filter_frame) - exit_program(1); - ist->pkt = av_packet_alloc(); if (!ist->pkt) exit_program(1); From 135e1c0adf155419a9546f02d620fb2aae95194b Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 20 Nov 2021 01:44:10 +0100 Subject: [PATCH 232/894] lavu/vulkan: check for initialization when freeing buffers What happens on startup is that ffmpeg.c initializes the filter, then frees it without feeding a single frame through. With no input frame, the filter lacks a hardware device. The rest of the uninit code checks if Vulkan objects exist, which they must if there's a hardware device, but vk->DeviceWaitIdle does not require an object. So, add a check for it. --- libavutil/vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index a6463de622..00df08b55e 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -350,7 +350,7 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) { FFVulkanFunctions *vk = &s->vkfn; - if (!buf) + if (!buf || !s->hwctx) return; vk->DeviceWaitIdle(s->hwctx->act_dev); From b159975e8027a1fa7cd4ad89aba98ab5fb2e65f9 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 20 Nov 2021 02:36:21 +0100 Subject: [PATCH 233/894] hwcontext_vulkan: check for non-flagged transfer queue families "All commands that are allowed on a queue that supports transfer operations are also allowed on a queue that supports either graphics or compute operations. Thus, if the capabilities of a queue family include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT capability separately for that queue family is optional." --- libavutil/hwcontext_vulkan.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 1e352d5ef7..f1e750cd3e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -832,6 +832,13 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) enc_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_ENCODE_BIT_KHR); dec_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_DECODE_BIT_KHR); + /* Signalling the transfer capabilities on a queue family is optional */ + if (tx_index < 0) { + tx_index = pick_queue_family(qf, num, VK_QUEUE_COMPUTE_BIT); + if (tx_index < 0) + tx_index = pick_queue_family(qf, num, VK_QUEUE_GRAPHICS_BIT); + } + hwctx->queue_family_index = -1; hwctx->queue_family_comp_index = -1; hwctx->queue_family_tx_index = -1; From 40cf317d09920e18045515cb867a512d071a6cf6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 19 Nov 2021 21:44:05 +0100 Subject: [PATCH 234/894] avcodec/smcenc: Move PutByteContext to stack This context is transient, so putting it on the stack is more natural. Also reduces codesize: 24E6->2296 B with GCC 10 and -O3. Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavcodec/smcenc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c index 5b0035b244..52795efb5f 100644 --- a/libavcodec/smcenc.c +++ b/libavcodec/smcenc.c @@ -39,7 +39,6 @@ typedef struct SMCContext { AVFrame *prev_frame; // buffer for previous source frame - PutByteContext pb; uint8_t mono_value; int nb_distinct; @@ -110,9 +109,9 @@ static int count_distinct_items(const uint8_t *block_values, s->color_octets[i][6] == distinct_values[x] || \ s->color_octets[i][7] == distinct_values[x]) -static void smc_encode_stream(SMCContext *s, const AVFrame *frame) +static void smc_encode_stream(SMCContext *s, const AVFrame *frame, + PutByteContext *pb) { - PutByteContext *pb = &s->pb; const uint8_t *src_pixels = (const uint8_t *)frame->data[0]; const int stride = frame->linesize[0]; const uint8_t *prev_pixels = (const uint8_t *)s->prev_frame->data[0]; @@ -492,6 +491,7 @@ static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, { SMCContext *s = avctx->priv_data; const AVFrame *pict = frame; + PutByteContext pb; uint8_t *pal; int ret; @@ -506,18 +506,18 @@ static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->key_frame = 0; } - bytestream2_init_writer(&s->pb, pkt->data, pkt->size); + bytestream2_init_writer(&pb, pkt->data, pkt->size); - bytestream2_put_be32(&s->pb, 0x00); + bytestream2_put_be32(&pb, 0x00); pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); if (!pal) return AVERROR(ENOMEM); memcpy(pal, frame->data[1], AVPALETTE_SIZE); - smc_encode_stream(s, pict); + smc_encode_stream(s, pict, &pb); - av_shrink_packet(pkt, bytestream2_tell_p(&s->pb)); + av_shrink_packet(pkt, bytestream2_tell_p(&pb)); pkt->data[0] = 0x0; From 645f705d6ac157ff29bbc45b7591d3a2f70b0b7f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 20 Nov 2021 16:19:15 +0100 Subject: [PATCH 235/894] av(codec|device): Don't cast pointers to int C99/C11 6.3.2.3 5: "Any pointer type may be converted to an integer type. [...] If the result cannot be represented in the integer type, the behavior is undefined." So stop casting pointers to int; use uintptr_t instead. Reviewed-by: Michael Niedermayer Signed-off-by: Andreas Rheinhardt --- libavcodec/dvdec.c | 4 ++-- libavcodec/x86/h264_qpel.c | 8 ++++---- libavcodec/x86/me_cmp_init.c | 6 +++--- libavcodec/x86/mpegvideoenc_template.c | 2 +- libavdevice/xcbgrab.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index a7424fd1d4..b72a67d01c 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -399,8 +399,8 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) int retried = 0; int sta; - av_assert1((((int) mb_bit_buffer) & 7) == 0); - av_assert1((((int) vs_bit_buffer) & 7) == 0); + av_assert1((((uintptr_t) mb_bit_buffer) & 7) == 0); + av_assert1((((uintptr_t) vs_bit_buffer) & 7) == 0); retry: diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index a2d8a64976..320d98933a 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -338,7 +338,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc21_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, halfHV, stride, SIZE);\ }\ @@ -348,7 +348,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc23_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, halfHV, stride, SIZE);\ }\ @@ -358,7 +358,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc12_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+2, halfHV, stride, SIZE, SIZE);\ }\ @@ -368,7 +368,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+3, halfHV, stride, SIZE, SIZE);\ }\ diff --git a/libavcodec/x86/me_cmp_init.c b/libavcodec/x86/me_cmp_init.c index 701eb1ab25..9af911bb88 100644 --- a/libavcodec/x86/me_cmp_init.c +++ b/libavcodec/x86/me_cmp_init.c @@ -131,7 +131,7 @@ static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, { int tmp; - av_assert2((((int) pix) & 7) == 0); + av_assert2(((uintptr_t) pix & 7) == 0); av_assert2((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ @@ -195,8 +195,8 @@ static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, { int tmp; - av_assert2((((int) pix1) & 7) == 0); - av_assert2((((int) pix2) & 7) == 0); + av_assert2(((uintptr_t)pix1 & 7) == 0); + av_assert2(((uintptr_t)pix2 & 7) == 0); av_assert2((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ diff --git a/libavcodec/x86/mpegvideoenc_template.c b/libavcodec/x86/mpegvideoenc_template.c index b32b1b0350..30c06a6b2c 100644 --- a/libavcodec/x86/mpegvideoenc_template.c +++ b/libavcodec/x86/mpegvideoenc_template.c @@ -109,7 +109,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, const uint16_t *qmat, *bias; LOCAL_ALIGNED_16(int16_t, temp_block, [64]); - av_assert2((7&(int)(&temp_block[0])) == 0); //did gcc align it correctly? + av_assert2((7&(uintptr_t)(&temp_block[0])) == 0); //did gcc align it correctly? //s->fdct (block); RENAME_FDCT(ff_fdct)(block); // cannot be anything else ... diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c index 8164101c5e..64a68ba497 100644 --- a/libavdevice/xcbgrab.c +++ b/libavdevice/xcbgrab.c @@ -277,7 +277,7 @@ static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get shared memory buffer.\n"); return AVERROR(ENOMEM); } - segment = (xcb_shm_seg_t)av_buffer_pool_buffer_get_opaque(buf); + segment = (xcb_shm_seg_t)(uintptr_t)av_buffer_pool_buffer_get_opaque(buf); iq = xcb_shm_get_image(c->conn, drawable, c->x, c->y, c->width, c->height, ~0, From 18f22bfb27e4919572b1b0a7f365a494364704f9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 19 Nov 2021 18:38:14 +0100 Subject: [PATCH 236/894] avcodec/h263: Inline constant Reviewed-by: Michael Niedermayer Signed-off-by: Andreas Rheinhardt --- libavcodec/h263.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h263.h b/libavcodec/h263.h index 491f2e0aac..70fd1ffdc0 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -103,7 +103,7 @@ static inline int h263_get_motion_length(int val, int f_code){ int l, bit_size, code; if (val == 0) { - return ff_mvtab[0][1]; + return 1; /* ff_mvtab[0][1] */ } else { bit_size = f_code - 1; /* modulo encoding */ From 203b0e3561dea1ec459be226d805abe73e7535e5 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Tue, 16 Nov 2021 18:44:32 +0530 Subject: [PATCH 237/894] avformat/mov: make STTS duration unsigned int As per 8.6.1.2.2 of ISO/IEC 14496-12:2015(E), STTS sample offsets are to be always stored as uint32_t. So far, they have been signed ints which led to desync in files with very large offsets. The MOVStts struct was used to store CTTS offsets as well. These can be negative in version 1. So a new struct MOVCtts was created and all declarations for CTTS usage changed to MOVCtts. --- libavformat/isom.h | 9 +++++++-- libavformat/mov.c | 20 ++++++++++---------- libavformat/movenc.c | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index f3c18c95be..ef8f19b18c 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -55,9 +55,14 @@ struct AVAESCTR; typedef struct MOVStts { unsigned int count; - int duration; + unsigned int duration; } MOVStts; +typedef struct MOVCtts { + unsigned int count; + int duration; +} MOVCtts; + typedef struct MOVStsc { int first; int count; @@ -168,7 +173,7 @@ typedef struct MOVStreamContext { uint8_t *sdtp_data; unsigned int ctts_count; unsigned int ctts_allocated_size; - MOVStts *ctts_data; + MOVCtts *ctts_data; unsigned int stsc_count; MOVStsc *stsc_data; unsigned int stsc_index; diff --git a/libavformat/mov.c b/libavformat/mov.c index 8a910a3165..451cb78bbf 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -77,7 +77,7 @@ typedef struct MOVParseTableEntry { static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); static int mov_read_mfra(MOVContext *c, AVIOContext *f); -static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, +static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration); static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, @@ -2938,7 +2938,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR(ENOMEM); for (i = 0; i < entries && !pb->eof_reached; i++) { - int sample_duration; + unsigned int sample_duration; unsigned int sample_count; unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries); MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size, @@ -3191,7 +3191,7 @@ static int get_edit_list_entry(MOVContext *mov, static int find_prev_closest_index(AVStream *st, AVIndexEntry *e_old, int nb_old, - MOVStts* ctts_data, + MOVCtts* ctts_data, int64_t ctts_count, int64_t timestamp_pts, int flag, @@ -3342,17 +3342,17 @@ static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ * Append a new ctts entry to ctts_data. * Returns the new ctts_count if successful, else returns -1. */ -static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, +static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration) { - MOVStts *ctts_buf_new; - const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVStts); + MOVCtts *ctts_buf_new; + const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVCtts); const size_t requested_size = min_size_needed > *allocated_size ? FFMAX(min_size_needed, 2 * (*allocated_size)) : min_size_needed; - if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1) + if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVCtts) - 1) return -1; ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size); @@ -3486,7 +3486,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) int nb_old = sti->nb_index_entries; const AVIndexEntry *e_old_end = e_old + nb_old; const AVIndexEntry *current = NULL; - MOVStts *ctts_data_old = msc->ctts_data; + MOVCtts *ctts_data_old = msc->ctts_data; int64_t ctts_index_old = 0; int64_t ctts_sample_old = 0; int64_t ctts_count_old = msc->ctts_count; @@ -3793,7 +3793,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int stps_index = 0; unsigned int i, j; uint64_t stream_size = 0; - MOVStts *ctts_data_old = sc->ctts_data; + MOVCtts *ctts_data_old = sc->ctts_data; unsigned int ctts_count_old = sc->ctts_count; if (sc->elst_count) { @@ -4754,7 +4754,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st = NULL; FFStream *sti = NULL; MOVStreamContext *sc; - MOVStts *ctts_data; + MOVCtts *ctts_data; uint64_t offset; int64_t dts, pts = AV_NOPTS_VALUE; int data_offset = 0; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 37d4403f7a..233aee62d4 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2434,7 +2434,7 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { MOVMuxContext *mov = s->priv_data; - MOVStts *ctts_entries; + MOVCtts *ctts_entries; uint32_t entries = 0; uint32_t atom_size; int i; From b1f1de084416768e8b4ba76b338029b974e518a2 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 22 Nov 2021 22:42:09 +0100 Subject: [PATCH 238/894] avutil/hwcontext_cuda: add option to use primary device context --- doc/ffmpeg.texi | 15 +++++++++++++++ libavutil/hwcontext_cuda.c | 24 ++++++++++++++++++++++++ libavutil/version.h | 2 +- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 8418573618..082eba5f14 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1096,6 +1096,21 @@ device type: @item cuda @var{device} is the number of the CUDA device. +The following options are recognized: +@table @option +@item primary_ctx +If set to 1, uses the primary device context instead of creating a new one. +@end table + +Examples: +@table @emph +@item -init_hw_device cuda:1 +Choose the second device on the system. + +@item -init_hw_device cuda:0,primary_ctx=1 +Choose the first device and use the primary device context. +@end table + @item dxva2 @var{device} is the number of the Direct3D 9 display adapter. diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index 48f7ecbdd3..ed7eeecb8b 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -376,6 +376,22 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { return 0; } +static int cuda_flags_from_opts(AVHWDeviceContext *device_ctx, + AVDictionary *opts, int *flags) +{ + AVDictionaryEntry *primary_ctx_opt = av_dict_get(opts, "primary_ctx", NULL, 0); + + if (primary_ctx_opt && strtol(primary_ctx_opt->value, NULL, 10)) { + av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA primary device context\n"); + *flags |= AV_CUDA_USE_PRIMARY_CONTEXT; + } else if (primary_ctx_opt) { + av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA primary device context\n"); + *flags &= ~AV_CUDA_USE_PRIMARY_CONTEXT; + } + + return 0; +} + static int cuda_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags) @@ -384,6 +400,10 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx, CudaFunctions *cu; int ret, device_idx = 0; + ret = cuda_flags_from_opts(device_ctx, opts, &flags); + if (ret < 0) + return ret; + if (device) device_idx = strtol(device, NULL, 0); @@ -419,6 +439,10 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, const char *src_uuid = NULL; int ret, i, device_count; + ret = cuda_flags_from_opts(device_ctx, opts, &flags); + if (ret < 0) + return ret; + #if CONFIG_VULKAN VkPhysicalDeviceIDProperties vk_idp = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, diff --git a/libavutil/version.h b/libavutil/version.h index d94fb691d7..a2615cd299 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 57 #define LIBAVUTIL_VERSION_MINOR 9 -#define LIBAVUTIL_VERSION_MICRO 100 +#define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From 2de6cd4ba450b40b2a60240d38a017b3dbbb18b9 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 22 Nov 2021 22:50:08 +0100 Subject: [PATCH 239/894] avutil/hwcontext_cuda: return more useful error codes from init functions --- libavutil/hwcontext_cuda.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index ed7eeecb8b..b96460920f 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -402,12 +402,13 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx, ret = cuda_flags_from_opts(device_ctx, opts, &flags); if (ret < 0) - return ret; + goto error; if (device) device_idx = strtol(device, NULL, 0); - if (cuda_device_init(device_ctx) < 0) + ret = cuda_device_init(device_ctx); + if (ret < 0) goto error; cu = hwctx->internal->cuda_dl; @@ -428,7 +429,7 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx, error: cuda_device_uninit(device_ctx); - return AVERROR_UNKNOWN; + return ret; } static int cuda_device_derive(AVHWDeviceContext *device_ctx, @@ -441,7 +442,7 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, ret = cuda_flags_from_opts(device_ctx, opts, &flags); if (ret < 0) - return ret; + goto error; #if CONFIG_VULKAN VkPhysicalDeviceIDProperties vk_idp = { @@ -466,16 +467,19 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, #undef TYPE #endif default: - return AVERROR(ENOSYS); + ret = AVERROR(ENOSYS); + goto error; } if (!src_uuid) { av_log(device_ctx, AV_LOG_ERROR, "Failed to get UUID of source device.\n"); + ret = AVERROR(EINVAL); goto error; } - if (cuda_device_init(device_ctx) < 0) + ret = cuda_device_init(device_ctx); + if (ret < 0) goto error; cu = hwctx->internal->cuda_dl; @@ -520,7 +524,7 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, error: cuda_device_uninit(device_ctx); - return AVERROR_UNKNOWN; + return ret; } const HWContextType ff_hwcontext_type_cuda = { From 0e22d2e59b4231a8e0e4bcca56b3f123b9474147 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 17 Nov 2021 23:10:58 +0800 Subject: [PATCH 240/894] avcodec/libaomenc: remove the redundant initialization For dst->have_sse will be assigned by ctx->have_sse soon(code line 23). Reviewed-by: James Zern Signed-off-by: Limin Wang --- libavcodec/libaomenc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 800fda0591..963cc1bcbc 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -948,7 +948,6 @@ static inline void cx_pktcpy(AOMContext *ctx, dst->sz = src->data.frame.sz; dst->buf = src->data.frame.buf; #ifdef AOM_FRAME_IS_INTRAONLY - dst->have_sse = 0; dst->frame_number = ++ctx->frame_number; dst->have_sse = ctx->have_sse; if (ctx->have_sse) { From e8380bbae6e3dfad9eaabf6ab0ba793221fd21f4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:24:07 +0100 Subject: [PATCH 241/894] ffmpeg: do not copy chroma_sample_location from the input stream It will be set from the supplied AVFrame later on. --- fftools/ffmpeg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c9a9cdfcd6..5325353bc9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3332,8 +3332,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (ist) { dec_ctx = ist->dec_ctx; - - enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; } if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { From 9d4e290ec46b29c305dbd5da5913d30efa9db80f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:29:56 +0100 Subject: [PATCH 242/894] ffmpeg: drop the -intra option It is undocumented and has been marked as deprecated since 2012. --- fftools/ffmpeg_opt.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 6732a29625..fc4f420616 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -176,7 +176,6 @@ int auto_conversion_filters = 1; int64_t stats_period = 500000; -static int intra_only = 0; static int file_overwrite = 0; static int no_file_overwrite = 0; static int do_psnr = 0; @@ -1822,8 +1821,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in } st->sample_aspect_ratio = video_enc->sample_aspect_ratio; - if (intra_only) - video_enc->gop_size = 0; MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); if (intra_matrix) { if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) { @@ -3772,8 +3769,6 @@ const OptionDef options[] = { "set pixel format", "format" }, { "bits_per_raw_sample", OPT_VIDEO | OPT_INT | HAS_ARG, { &frame_bits_per_raw_sample }, "set the number of bits per raw sample", "number" }, - { "intra", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &intra_only }, - "deprecated use -g 1" }, { "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) }, "disable video" }, { "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | From d013453caafcc44c74d4bdbaa99ee4e8f32414cb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:32:25 +0100 Subject: [PATCH 243/894] ffmpeg: drop the -deinterlace option It is undocumented and has been deprecated since 2013. --- fftools/ffmpeg_filter.c | 17 ----------------- fftools/ffmpeg_opt.c | 3 --- 2 files changed, 20 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index c70903295f..452b689d62 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -805,23 +805,6 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, return ret; } - if (do_deinterlace) { - AVFilterContext *yadif; - - snprintf(name, sizeof(name), "deinterlace_in_%d_%d", - ist->file_index, ist->st->index); - if ((ret = avfilter_graph_create_filter(&yadif, - avfilter_get_by_name("yadif"), - name, "", NULL, - fg->graph)) < 0) - return ret; - - if ((ret = avfilter_link(last_filter, 0, yadif, 0)) < 0) - return ret; - - last_filter = yadif; - } - snprintf(name, sizeof(name), "trim_in_%d_%d", ist->file_index, ist->st->index); if (copy_ts) { diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index fc4f420616..aec60a2532 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -153,7 +153,6 @@ int audio_volume = 256; int audio_sync_method = 0; int video_sync_method = VSYNC_AUTO; float frame_drop_threshold = 0; -int do_deinterlace = 0; int do_benchmark = 0; int do_benchmark_all = 0; int do_hex_dump = 0; @@ -3788,8 +3787,6 @@ const OptionDef options[] = { { "passlogfile", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(passlogfiles) }, "select two pass log file name prefix", "prefix" }, - { "deinterlace", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_deinterlace }, - "this option is deprecated, use the yadif filter instead" }, { "psnr", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_psnr }, "calculate PSNR of compressed frames" }, { "vstats", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_vstats }, From a44098152b85b1a121efa39e1c0dc8cc8c27b0ed Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:34:05 +0100 Subject: [PATCH 244/894] ffmpeg: drop the -vc option It is undocumented and has been deprecated since 2012. --- fftools/ffmpeg_opt.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index aec60a2532..c3c28ad729 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -312,12 +312,6 @@ static int opt_sameq(void *optctx, const char *opt, const char *arg) return AVERROR(EINVAL); } -static int opt_video_channel(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n"); - return opt_default(optctx, "channel", arg); -} - static int opt_video_standard(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n"); @@ -3893,8 +3887,6 @@ const OptionDef options[] = { "set canvas size (WxH or abbreviation)", "size" }, /* grab options */ - { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_channel }, - "deprecated, use -channel", "channel" }, { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_standard }, "deprecated, use -standard", "standard" }, { "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" }, From 5ebdf9bb50ae4769bd3acbfe1e2ab0db154e52cd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:34:37 +0100 Subject: [PATCH 245/894] ffmpeg: drop the -tvstd option It is undocumented and has been deprecated since 2012. --- fftools/ffmpeg_opt.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index c3c28ad729..ca87171fe0 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -312,12 +312,6 @@ static int opt_sameq(void *optctx, const char *opt, const char *arg) return AVERROR(EINVAL); } -static int opt_video_standard(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n"); - return opt_default(optctx, "standard", arg); -} - static int opt_audio_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -3887,8 +3881,6 @@ const OptionDef options[] = { "set canvas size (WxH or abbreviation)", "size" }, /* grab options */ - { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_standard }, - "deprecated, use -standard", "standard" }, { "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" }, /* muxer options */ From 84cb255c20800ce8bc12a93a1b63475ea5413010 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:35:54 +0100 Subject: [PATCH 246/894] ffmpeg: drop -sameq/-samequant options They did nothing but return an error since 2012. --- fftools/ffmpeg_opt.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index ca87171fe0..45ed727e5e 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -303,15 +303,6 @@ static int opt_stats_period(void *optctx, const char *opt, const char *arg) return 0; } -static int opt_sameq(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_ERROR, "Option '%s' was removed. " - "If you are looking for an option to preserve the quality (which is not " - "what -%s was for), use -qscale 0 or an equivalent quality factor option.\n", - opt, opt); - return AVERROR(EINVAL); -} - static int opt_audio_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -3764,10 +3755,6 @@ const OptionDef options[] = { { "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_video_codec }, "force video codec ('copy' to copy stream)", "codec" }, - { "sameq", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_sameq }, - "Removed" }, - { "same_quant", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_sameq }, - "Removed" }, { "timecode", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_timecode }, "set initial TimeCode value.", "hh:mm:ss[:;.]ff" }, { "pass", OPT_VIDEO | HAS_ARG | OPT_SPEC | OPT_INT | OPT_OUTPUT, { .off = OFFSET(pass) }, From 823cea519778f3c6b5119cfdb75219289564db57 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 Nov 2021 18:38:03 +0100 Subject: [PATCH 247/894] ffmpeg: drop -isync, which did nothing since 2012 --- fftools/ffmpeg_opt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 45ed727e5e..e55b584fd4 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -178,7 +178,6 @@ int64_t stats_period = 500000; static int file_overwrite = 0; static int no_file_overwrite = 0; static int do_psnr = 0; -static int input_sync; static int input_stream_potentially_available = 0; static int ignore_unknown_streams = 0; static int copy_unknown_streams = 0; @@ -3867,9 +3866,6 @@ const OptionDef options[] = { { "canvas_size", OPT_SUBTITLE | HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFFSET(canvas_sizes) }, "set canvas size (WxH or abbreviation)", "size" }, - /* grab options */ - { "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" }, - /* muxer options */ { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_max_delay) }, "set the maximum demux-decode delay", "seconds" }, From 9dd104f6e263dce770541074d99b5286524f2a8b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 15 Nov 2021 16:14:49 +0100 Subject: [PATCH 248/894] ffmpeg: drop obsolete rotation API remnants No demuxers export the "rotate" metadata tag anymore. --- fftools/ffmpeg.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5325353bc9..3761ea0c38 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3325,11 +3325,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) set_encoder_id(output_files[ost->file_index], ost); - // Muxers use AV_PKT_DATA_DISPLAYMATRIX to signal rotation. On the other - // hand, the legacy API makes demuxers set "rotate" metadata entries, - // which have to be filtered out to prevent leaking them to output files. - av_dict_set(&ost->st->metadata, "rotate", NULL, 0); - if (ist) { dec_ctx = ist->dec_ctx; } From c2a356d5835b62c6f4a9263ac9c917d6a31fe431 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Wed, 24 Nov 2021 12:11:52 +0800 Subject: [PATCH 249/894] avutil/hwcontext_vulkan: check if created before destroying the device Signed-off-by: Wu Jianhua --- libavutil/hwcontext_vulkan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f1e750cd3e..4ac1058181 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1150,7 +1150,8 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - vk->DestroyDevice(hwctx->act_dev, hwctx->alloc); + if (hwctx->act_dev) + vk->DestroyDevice(hwctx->act_dev, hwctx->alloc); if (p->debug_ctx) vk->DestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx, From 7e9e2cf93b6e22eaec72837ab59ac654c19b8d99 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Wed, 24 Nov 2021 12:11:53 +0800 Subject: [PATCH 250/894] avutil/hwcontext_vulkan: check if created before destroying the instance Signed-off-by: Wu Jianhua --- libavutil/hwcontext_vulkan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 4ac1058181..644ed947f8 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1157,7 +1157,8 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) vk->DestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx, hwctx->alloc); - vk->DestroyInstance(hwctx->inst, hwctx->alloc); + if (hwctx->inst) + vk->DestroyInstance(hwctx->inst, hwctx->alloc); if (p->libvulkan) dlclose(p->libvulkan); From 1a5930b55494b5d598c618283b24f12ad1ac38a2 Mon Sep 17 00:00:00 2001 From: Matt Oliver Date: Wed, 20 Oct 2021 06:28:53 +1100 Subject: [PATCH 251/894] libvpxdec: Correct linking against variables. Instead link against the function that returns the correct variable. This fixes linking errors with dlls with msvc. --- libavcodec/libvpxdec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 42d1b8ab1c..b2aa205036 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -242,11 +242,11 @@ static int vpx_decode(AVCodecContext *avctx, &ctx->decoder_alpha, #if CONFIG_LIBVPX_VP8_DECODER && CONFIG_LIBVPX_VP9_DECODER (avctx->codec_id == AV_CODEC_ID_VP8) ? - &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo + vpx_codec_vp8_dx() : vpx_codec_vp9_dx() #elif CONFIG_LIBVPX_VP8_DECODER - &vpx_codec_vp8_dx_algo + vpx_codec_vp8_dx() #else - &vpx_codec_vp9_dx_algo + vpx_codec_vp9_dx() #endif ); if (ret) @@ -350,7 +350,7 @@ static av_cold int vpx_free(AVCodecContext *avctx) static av_cold int vp8_init(AVCodecContext *avctx) { VPxContext *ctx = avctx->priv_data; - return vpx_init(avctx, &ctx->decoder, &vpx_codec_vp8_dx_algo); + return vpx_init(avctx, &ctx->decoder, vpx_codec_vp8_dx()); } const AVCodec ff_libvpx_vp8_decoder = { @@ -372,7 +372,7 @@ const AVCodec ff_libvpx_vp8_decoder = { static av_cold int vp9_init(AVCodecContext *avctx) { VPxContext *ctx = avctx->priv_data; - return vpx_init(avctx, &ctx->decoder, &vpx_codec_vp9_dx_algo); + return vpx_init(avctx, &ctx->decoder, vpx_codec_vp9_dx()); } AVCodec ff_libvpx_vp9_decoder = { From 3399bbab4dcfb8dec3bb1dd238816908791118f3 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 10 Nov 2021 19:35:47 +0800 Subject: [PATCH 252/894] avformat/rtpdec_rfc4175: use rawvideo for uyvy422 Reviewed-by: Lynne Signed-off-by: Limin Wang --- libavformat/rtpdec_rfc4175.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index f50cad76d2..f13736bc3c 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -55,9 +55,11 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data) if (data->depth == 8) { data->pgroup = 4; pixfmt = AV_PIX_FMT_UYVY422; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; } else if (data->depth == 10) { data->pgroup = 5; pixfmt = AV_PIX_FMT_YUV422P10; + stream->codecpar->codec_id = AV_CODEC_ID_BITPACKED; } else { return AVERROR_INVALIDDATA; } @@ -268,7 +270,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, const RTPDynamicProtocolHandler ff_rfc4175_rtp_handler = { .enc_name = "raw", .codec_type = AVMEDIA_TYPE_VIDEO, - .codec_id = AV_CODEC_ID_BITPACKED, + .codec_id = AV_CODEC_ID_NONE, .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = rfc4175_parse_sdp_line, .parse_packet = rfc4175_handle_packet, From 05b0c66313abc87505e9298f432476c33588c932 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 24 Nov 2021 19:05:50 +0800 Subject: [PATCH 253/894] avformat/rtpdec_rfc4175: support for yuv420p format Reviewed-by: Lynne Signed-off-by: Limin Wang --- libavformat/rtpdec_rfc4175.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index f13736bc3c..5a7058bc14 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -63,6 +63,17 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data) } else { return AVERROR_INVALIDDATA; } + } else if (!strncmp(data->sampling, "YCbCr-4:2:0", 11)) { + tag = MKTAG('I', '4', '2', '0'); + data->xinc = 4; + + if (data->depth == 8) { + data->pgroup = 6; + pixfmt = AV_PIX_FMT_YUV420P; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + return AVERROR_INVALIDDATA; + } } else { return AVERROR_INVALIDDATA; } From 4f5352d5fe6ce801cfd0a45e8564373eeec595da Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 13 Nov 2021 18:06:02 +0800 Subject: [PATCH 254/894] avformat/rtpenc: adds partial support for the RFC 4175 Reviewed-by: Lynne Signed-off-by: Limin Wang --- Changelog | 1 + libavformat/Makefile | 1 + libavformat/rtpenc.c | 4 ++ libavformat/rtpenc.h | 1 + libavformat/rtpenc_rfc4175.c | 116 +++++++++++++++++++++++++++++++++++ libavformat/sdp.c | 25 ++++++++ libavformat/version.h | 2 +- 7 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 libavformat/rtpenc_rfc4175.c diff --git a/Changelog b/Changelog index 31a0d5ef5d..2035c27021 100644 --- a/Changelog +++ b/Changelog @@ -31,6 +31,7 @@ version : - varblur video filter - huesaturation video filter - colorspectrum source video filter +- RTP packetizer for uncompressed video (RFC 4175) version 4.4: diff --git a/libavformat/Makefile b/libavformat/Makefile index 3d6c8ef8f5..a19d2e0c88 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -482,6 +482,7 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_jpeg.o \ rtpenc_mpv.o \ rtpenc.o \ + rtpenc_rfc4175.o \ rtpenc_vc2hq.o \ rtpenc_vp8.o \ rtpenc_vp9.o \ diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 2a1c176066..4f115cc77e 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -84,6 +84,7 @@ static int is_supported(enum AVCodecID id) case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_SPEEX: case AV_CODEC_ID_OPUS: + case AV_CODEC_ID_RAWVIDEO: return 1; default: return 0; @@ -619,6 +620,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) case AV_CODEC_ID_MJPEG: ff_rtp_send_jpeg(s1, pkt->data, size); break; + case AV_CODEC_ID_RAWVIDEO: + ff_rtp_send_raw_rfc4175 (s1, pkt->data, size); + break; case AV_CODEC_ID_OPUS: if (size > s->max_payload_size) { av_log(s1, AV_LOG_ERROR, diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index 62dc9ab10a..70ea85bf3f 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -95,6 +95,7 @@ void ff_rtp_send_vc2hq(AVFormatContext *s1, const uint8_t *buf, int size, int in void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_vp9(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buff, int size); +void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size); const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start, const uint8_t *av_restrict end); diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c new file mode 100644 index 0000000000..6fa34b64cb --- /dev/null +++ b/libavformat/rtpenc_rfc4175.c @@ -0,0 +1,116 @@ +/* + * RTP Packetization of RAW video (RFC4175) + * Copyright (c) 2021 Limin Wang + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avformat.h" +#include "rtpenc.h" + +void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) +{ + RTPMuxContext *s = s1->priv_data; + int width = s1->streams[0]->codecpar->width; + int height = s1->streams[0]->codecpar->height; + int xinc, yinc, pgroup; + int field = 0; + int i = 0; + int offset = 0; + + s->timestamp = s->cur_timestamp; + switch (s1->streams[0]->codecpar->format) { + case AV_PIX_FMT_UYVY422: + xinc = yinc = 2; + pgroup = 4; + break; + case AV_PIX_FMT_YUV420P: + xinc = yinc = 4; + pgroup = 6; + break; + default: + return; + } + + while (i < height) { + int left = s->max_payload_size; + uint8_t *dest = s->buf; + uint8_t *headers; + const int head_size = 6; + int next_line; + int length, cont, pixels; + + /* Extended Sequence Number */ + *dest++ = 0; + *dest++ = 0; + left -= 2; + + headers = dest; + do { + pixels = width * xinc - offset; + length = (pixels * pgroup) / xinc; + + left -= head_size; + if (left >= length) { + next_line = 1; + } else { + pixels = (left / pgroup) * xinc; + length = (pixels * pgroup) / xinc; + next_line = 0; + } + left -= length; + + /* Length */ + *dest++ = (length >> 8) & 0xff; + *dest++ = length & 0xff; + + /* Line No */ + *dest++ = ((i >> 8) & 0x7f) | ((field << 7) & 0x80); + *dest++ = i & 0xff; + if (next_line) i += yinc; + + cont = (left > (head_size + pgroup) && i < height) ? 0x80 : 0x00; + /* Offset and Continuation marker */ + *dest++ = ((offset >> 8) & 0x7f) | cont; + *dest++ = offset & 0xff; + + if (next_line) + offset = 0; + else + offset += pixels; + } while (cont); + + do { + int l_line; + int l_off; + int copy_offset; + + length = (headers[0] << 8) | headers[1]; + l_line = ((headers[2] & 0x7f) << 8) | headers[3]; + l_off = ((headers[4] & 0x7f) << 8) | headers[5]; + cont = headers[4] & 0x80; + headers += head_size; + + copy_offset = (l_line * width + l_off) * pgroup / xinc; + if (copy_offset + length > size) + break; + memcpy (dest, buf + copy_offset, length); + dest += length; + } while (cont); + + ff_rtp_send_data (s1, s->buf, s->max_payload_size - left, i >= height); + } +} diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 1200e553f9..cc04d70c0d 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -660,6 +660,31 @@ static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int p->width, p->height, pix_fmt, config); break; } + case AV_CODEC_ID_RAWVIDEO: { + const char *pix_fmt; + int bit_depth = 8; + + switch (p->format) { + case AV_PIX_FMT_UYVY422: + pix_fmt = "YCbCr-4:2:2"; + break; + case AV_PIX_FMT_YUV420P: + pix_fmt = "YCbCr-4:2:0"; + break; + default: + av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return NULL; + } + + av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" + "a=fmtp:%d sampling=%s; " + "width=%d; height=%d; " + "depth=%d\r\n", + payload_type, payload_type, + pix_fmt, p->width, p->height, bit_depth); + break; + } + case AV_CODEC_ID_VP8: av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", payload_type); diff --git a/libavformat/version.h b/libavformat/version.h index ae2b873197..0705ee4112 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 #define LIBAVFORMAT_VERSION_MINOR 9 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MICRO 102 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 130250d3affb26222b76b73185308337dcbb431c Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 24 Nov 2021 16:50:06 +0800 Subject: [PATCH 255/894] avcodec: rename bitpacked.c to bitpacked_dec.c Reviewed-by: Lynne Signed-off-by: Limin Wang --- libavcodec/Makefile | 2 +- libavcodec/{bitpacked.c => bitpacked_dec.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename libavcodec/{bitpacked.c => bitpacked_dec.c} (100%) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 14fbd2ecbc..fbb2b791d8 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -243,7 +243,7 @@ OBJS-$(CONFIG_BINK_DECODER) += bink.o binkdsp.o OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o OBJS-$(CONFIG_BINTEXT_DECODER) += bintext.o cga_data.o -OBJS-$(CONFIG_BITPACKED_DECODER) += bitpacked.o +OBJS-$(CONFIG_BITPACKED_DECODER) += bitpacked_dec.o OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmvaudio.o diff --git a/libavcodec/bitpacked.c b/libavcodec/bitpacked_dec.c similarity index 100% rename from libavcodec/bitpacked.c rename to libavcodec/bitpacked_dec.c From 3436864e681bfe81b9de3821e822ca636264ad65 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 25 Nov 2021 09:45:43 +0800 Subject: [PATCH 256/894] avcodec: suppport for bitpacked encode Reviewed-by: Lynne Signed-off-by: Limin Wang --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/bitpacked_enc.c | 118 +++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 libavcodec/bitpacked_enc.c diff --git a/Changelog b/Changelog index 2035c27021..a66231b4d8 100644 --- a/Changelog +++ b/Changelog @@ -32,6 +32,7 @@ version : - huesaturation video filter - colorspectrum source video filter - RTP packetizer for uncompressed video (RFC 4175) +- bitpacked encoder version 4.4: diff --git a/libavcodec/Makefile b/libavcodec/Makefile index fbb2b791d8..6be90cd5c0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -244,6 +244,7 @@ OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o OBJS-$(CONFIG_BINTEXT_DECODER) += bintext.o cga_data.o OBJS-$(CONFIG_BITPACKED_DECODER) += bitpacked_dec.o +OBJS-$(CONFIG_BITPACKED_ENCODER) += bitpacked_enc.o OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmvaudio.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 9ede09be17..89d65266c8 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -65,6 +65,7 @@ extern const AVCodec ff_bethsoftvid_decoder; extern const AVCodec ff_bfi_decoder; extern const AVCodec ff_bink_decoder; extern const AVCodec ff_bitpacked_decoder; +extern const AVCodec ff_bitpacked_encoder; extern const AVCodec ff_bmp_encoder; extern const AVCodec ff_bmp_decoder; extern const AVCodec ff_bmv_video_decoder; diff --git a/libavcodec/bitpacked_enc.c b/libavcodec/bitpacked_enc.c new file mode 100644 index 0000000000..3e0ba0055e --- /dev/null +++ b/libavcodec/bitpacked_enc.c @@ -0,0 +1,118 @@ +/* + * bitpacked encoder + * + * Copyright (c) 2021 Limin Wang + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "encode.h" +#include "internal.h" +#include "put_bits.h" +#include "libavutil/pixdesc.h" + +struct BitpackedContext { + int (*encode)(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame); +}; + +static int encode_yuv422p10(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame) +{ + const int buf_size = avctx->height * avctx->width * avctx->bits_per_coded_sample / 8; + int ret; + uint8_t *dst; + const uint16_t *y; + const uint16_t *u; + const uint16_t *v; + PutBitContext pb; + + ret = ff_get_encode_buffer(avctx, pkt, buf_size, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; + } + dst = pkt->data; + + init_put_bits(&pb, dst, buf_size); + + for (int i = 0; i < avctx->height; i++) { + y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]); + u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]); + v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]); + + for (int j = 0; j < avctx->width; j += 2) { + /* u, y0, v, y1 */ + put_bits(&pb, 10, av_clip_uintp2(*u++, 10)); + put_bits(&pb, 10, av_clip_uintp2(*y++, 10)); + put_bits(&pb, 10, av_clip_uintp2(*v++, 10)); + put_bits(&pb, 10, av_clip_uintp2(*y++, 10)); + } + } + flush_put_bits(&pb); + + return 0; +} + + +static av_cold int encode_init(AVCodecContext *avctx) +{ + struct BitpackedContext *s = avctx->priv_data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "bitpacked needs even width\n"); + return AVERROR(EINVAL); + } + + avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc); + avctx->bit_rate = ff_guess_coded_bitrate(avctx); + + if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) + s->encode = encode_yuv422p10; + else + return AVERROR(EINVAL); + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + struct BitpackedContext *s = avctx->priv_data; + int ret; + + ret = s->encode(avctx, pkt, frame); + if (ret) + return ret; + + *got_packet = 1; + return 0; +} + +const AVCodec ff_bitpacked_encoder = { + .name = "bitpacked", + .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BITPACKED, + .priv_data_size = sizeof(struct BitpackedContext), + .capabilities = AV_CODEC_CAP_DR1, + .init = encode_init, + .encode2 = encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 4d3000364a..58e3322e9a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 59 #define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 7b55f95f71559b2e76bdc6e7d6dcf12b3b5a8677 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 11 Nov 2021 22:39:14 +0800 Subject: [PATCH 257/894] avformat: suppport YUV 4:2:2 10-bit for rfc4175 Reviewed-by: Lynne Signed-off-by: Limin Wang --- libavformat/rtpenc.c | 2 ++ libavformat/rtpenc_rfc4175.c | 4 ++++ libavformat/sdp.c | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 4f115cc77e..17f5d9d308 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -85,6 +85,7 @@ static int is_supported(enum AVCodecID id) case AV_CODEC_ID_SPEEX: case AV_CODEC_ID_OPUS: case AV_CODEC_ID_RAWVIDEO: + case AV_CODEC_ID_BITPACKED: return 1; default: return 0; @@ -620,6 +621,7 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) case AV_CODEC_ID_MJPEG: ff_rtp_send_jpeg(s1, pkt->data, size); break; + case AV_CODEC_ID_BITPACKED: case AV_CODEC_ID_RAWVIDEO: ff_rtp_send_raw_rfc4175 (s1, pkt->data, size); break; diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c index 6fa34b64cb..4623b4ac23 100644 --- a/libavformat/rtpenc_rfc4175.c +++ b/libavformat/rtpenc_rfc4175.c @@ -37,6 +37,10 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) xinc = yinc = 2; pgroup = 4; break; + case AV_PIX_FMT_YUV422P10: + xinc = yinc = 2; + pgroup = 5; + break; case AV_PIX_FMT_YUV420P: xinc = yinc = 4; pgroup = 6; diff --git a/libavformat/sdp.c b/libavformat/sdp.c index cc04d70c0d..5ad2a54474 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -660,6 +660,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int p->width, p->height, pix_fmt, config); break; } + case AV_CODEC_ID_BITPACKED: case AV_CODEC_ID_RAWVIDEO: { const char *pix_fmt; int bit_depth = 8; @@ -668,6 +669,10 @@ static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int case AV_PIX_FMT_UYVY422: pix_fmt = "YCbCr-4:2:2"; break; + case AV_PIX_FMT_YUV422P10: + pix_fmt = "YCbCr-4:2:2"; + bit_depth = 10; + break; case AV_PIX_FMT_YUV420P: pix_fmt = "YCbCr-4:2:0"; break; From 522f577d7eca66c65aece841610cb008a10c1a2e Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 24 Nov 2021 19:14:17 +0800 Subject: [PATCH 258/894] avformat/rtp: support RGB/BGR for rfc4175 Reviewed-by: Lynne Signed-off-by: Limin Wang --- libavformat/rtpdec_rfc4175.c | 20 ++++++++++++++++++++ libavformat/rtpenc_rfc4175.c | 8 ++++++++ libavformat/sdp.c | 6 ++++++ 3 files changed, 34 insertions(+) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index 5a7058bc14..7feefd2fff 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -74,6 +74,26 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data) } else { return AVERROR_INVALIDDATA; } + } else if (!strncmp(data->sampling, "RGB", 3)) { + tag = MKTAG('R', 'G', 'B', 24); + if (data->depth == 8) { + data->xinc = 1; + data->pgroup = 3; + pixfmt = AV_PIX_FMT_RGB24; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + return AVERROR_INVALIDDATA; + } + } else if (!strncmp(data->sampling, "BGR", 3)) { + tag = MKTAG('B', 'G', 'R', 24); + if (data->depth == 8) { + data->xinc = 1; + data->pgroup = 3; + pixfmt = AV_PIX_FMT_BGR24; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + return AVERROR_INVALIDDATA; + } } else { return AVERROR_INVALIDDATA; } diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c index 4623b4ac23..ea4c3705f3 100644 --- a/libavformat/rtpenc_rfc4175.c +++ b/libavformat/rtpenc_rfc4175.c @@ -45,6 +45,14 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) xinc = yinc = 4; pgroup = 6; break; + case AV_PIX_FMT_RGB24: + xinc = yinc = 1; + pgroup = 3; + break; + case AV_PIX_FMT_BGR24: + xinc = yinc = 1; + pgroup = 3; + break; default: return; } diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 5ad2a54474..a41c2cf655 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -676,6 +676,12 @@ static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int case AV_PIX_FMT_YUV420P: pix_fmt = "YCbCr-4:2:0"; break; + case AV_PIX_FMT_RGB24: + pix_fmt = "RGB"; + break; + case AV_PIX_FMT_BGR24: + pix_fmt = "BGR"; + break; default: av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); return NULL; From b46817d9c3fe620ba02f2b3144444c431c6ba552 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 9 Jun 2021 17:01:02 -0300 Subject: [PATCH 259/894] avformat/http: prevent truncation of sanitized_path path1 and sanitized_path are both MAX_URL_SIZE bytes long, yet the latter is copied from the former with the addition of one extra character. Should fix a -Wformat-truncation warning. Signed-off-by: James Almer --- libavformat/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index fdfbc69da1..91650be47a 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -194,7 +194,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) char *hashmark; char hostname[1024], hoststr[1024], proto[10]; char auth[1024], proxyauth[1024] = ""; - char path1[MAX_URL_SIZE], sanitized_path[MAX_URL_SIZE]; + char path1[MAX_URL_SIZE], sanitized_path[MAX_URL_SIZE + 1]; char buf[1024], urlbuf[MAX_URL_SIZE]; int port, use_proxy, err, location_changed = 0; HTTPContext *s = h->priv_data; From 6f10f4a47948525174e654c9e312871dacdfc300 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 19 Nov 2021 21:26:52 +0100 Subject: [PATCH 260/894] avformat/libsrt: add missing version check for snddropdelay Signed-off-by: Marton Balint --- libavformat/libsrt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c index 145eea2f7c..19b9cb9895 100644 --- a/libavformat/libsrt.c +++ b/libavformat/libsrt.c @@ -320,7 +320,9 @@ static int libsrt_set_options_pre(URLContext *h, int fd) int latency = s->latency / 1000; int rcvlatency = s->rcvlatency / 1000; int peerlatency = s->peerlatency / 1000; +#if SRT_VERSION_VALUE >= 0x010302 int snddropdelay = s->snddropdelay > 0 ? s->snddropdelay / 1000 : s->snddropdelay; +#endif int connect_timeout = s->connect_timeout; if ((s->mode == SRT_MODE_RENDEZVOUS && libsrt_setsockopt(h, fd, SRTO_RENDEZVOUS, "SRTO_RENDEZVOUS", &yes, sizeof(yes)) < 0) || From 0b9dbfab480004d7245013e1f9bf94c40a63f77f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 22 Nov 2021 00:56:05 +0100 Subject: [PATCH 261/894] avformat/mpegts: fix stream index in verbose log message Signed-off-by: Marton Balint --- libavformat/mpegts.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 29a267436f..36ab7ab3af 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -2238,11 +2238,10 @@ static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int p int stream_identifier, int pmt_stream_idx, struct Program *p) { AVFormatContext *s = ts->stream; - int i; AVStream *found = NULL; if (stream_identifier) { /* match based on "stream identifier descriptor" if present */ - for (i = 0; i < p->nb_streams; i++) { + for (int i = 0; i < p->nb_streams; i++) { if (p->streams[i].stream_identifier == stream_identifier) if (!found || pmt_stream_idx == i) /* fallback to idx based guess if multiple streams have the same identifier */ found = s->streams[p->streams[i].idx]; @@ -2255,7 +2254,7 @@ static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int p av_log(ts->stream, AV_LOG_VERBOSE, "re-using existing %s stream %d (pid=0x%x) for new pid=0x%x\n", av_get_media_type_string(found->codecpar->codec_type), - i, found->id, pid); + found->index, found->id, pid); } return found; From e38551180ec4394e0f9050f624486c1ec796dba4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 26 Nov 2021 00:49:29 +0100 Subject: [PATCH 262/894] avfilter/af_biquads: add svf transform type --- doc/filters.texi | 9 ++++ libavfilter/af_biquads.c | 95 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index c3ccaf97c4..3731a14521 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1885,6 +1885,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3249,6 +3250,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3336,6 +3338,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3433,6 +3436,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3515,6 +3519,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -4265,6 +4270,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -4766,6 +4772,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -5116,6 +5123,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -6340,6 +6348,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index adbae5892d..ee42b2a034 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -99,6 +99,7 @@ enum TransformType { DII, TDII, LATT, + SVF, NB_TTYPE, }; @@ -419,6 +420,54 @@ BIQUAD_LATT_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) BIQUAD_LATT_FILTER(flt, float, -1., 1., 0) BIQUAD_LATT_FILTER(dbl, double, -1., 1., 0) +#define BIQUAD_SVF_FILTER(name, type, min, max, need_clipping) \ +static void biquad_svf_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *y0, double *y1, \ + double *unused1, double *unused2, \ + double b0, double b1, double b2, \ + double a1, double a2, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double s0 = *y0; \ + double s1 = *y1; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double in, out; \ + double t0, t1; \ + \ + for (int i = 0; i < len; i++) { \ + in = ibuf[i]; \ + out = b2 * in + s0; \ + t0 = b0 * in + a1 * s0 + s1; \ + t1 = b1 * in + a2 * s0; \ + s0 = t0; \ + s1 = t1; \ + \ + out = out * wet + in * dry; \ + if (disabled) { \ + obuf[i] = in; \ + } else if (need_clipping && out < min) { \ + (*clippings)++; \ + obuf[i] = min; \ + } else if (need_clipping && out > max) { \ + (*clippings)++; \ + obuf[i] = max; \ + } else { \ + obuf[i] = out; \ + } \ + } \ + *y0 = s0; \ + *y1 = s1; \ +} + +BIQUAD_SVF_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +BIQUAD_SVF_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) +BIQUAD_SVF_FILTER(flt, float, -1., 1., 0) +BIQUAD_SVF_FILTER(dbl, double, -1., 1., 0) + static void convert_dir2latt(BiquadsContext *s) { double k0, k1, v0, v1, v2; @@ -436,6 +485,24 @@ static void convert_dir2latt(BiquadsContext *s) s->b2 = v2; } +static void convert_dir2svf(BiquadsContext *s) +{ + double a[2]; + double b[3]; + + a[0] = -s->a1; + a[1] = -s->a2; + b[0] = s->b1 - s->a1 * s->b0; + b[1] = s->b2 - s->a2 * s->b0; + b[2] = s->b0; + + s->a1 = a[0]; + s->a2 = a[1]; + s->b0 = b[0]; + s->b1 = b[1]; + s->b2 = b[2]; +} + static int config_filter(AVFilterLink *outlink, int reset) { AVFilterContext *ctx = outlink->src; @@ -724,6 +791,23 @@ static int config_filter(AVFilterLink *outlink, int reset) default: av_assert0(0); } break; + case SVF: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_svf_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_svf_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_svf_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_svf_dbl; + break; + default: av_assert0(0); + } + break; default: av_assert0(0); } @@ -732,6 +816,8 @@ static int config_filter(AVFilterLink *outlink, int reset) if (s->transform_type == LATT) convert_dir2latt(s); + else if (s->transform_type == SVF) + convert_dir2svf(s); return 0; } @@ -906,6 +992,7 @@ static const AVOption equalizer_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -947,6 +1034,7 @@ static const AVOption bass_lowshelf_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -995,6 +1083,7 @@ static const AVOption treble_highshelf_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -1042,6 +1131,7 @@ static const AVOption bandpass_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -1079,6 +1169,7 @@ static const AVOption bandreject_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -1118,6 +1209,7 @@ static const AVOption lowpass_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -1157,6 +1249,7 @@ static const AVOption highpass_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -1196,6 +1289,7 @@ static const AVOption allpass_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, @@ -1228,6 +1322,7 @@ static const AVOption biquad_options[] = { {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, From 1e5acc1b5985c58e3ec15f136c0c8d662ced3510 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 24 Nov 2021 20:17:09 +0100 Subject: [PATCH 263/894] configure: do not include -lvulkan to cflags in vulkan's pkg-config check Also fixes the non-pkg-config check. --- configure | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/configure b/configure index d068b11073..e6cee21142 100755 --- a/configure +++ b/configure @@ -1464,13 +1464,13 @@ test_pkg_config_cpp(){ cond="$4" shift 4 disable $name - test_cmd $pkg_config --exists --print-errors $pkg_version || return + test_cmd $pkg_config --exists --print-errors $pkg_version || returnddd pkg_cflags=$($pkg_config --cflags $pkg_config_flags $pkg) - pkg_incdir=$($pkg_config --variable=includedir $pkg_config_flags $pkg) + pkg_incflags=$($pkg_config --cflags-onyl-I $pkg_config_flags $pkg) test_cpp_condition "$pkg_incdir/$headers" "$cond" "$@" && enable $name && set_sanitized "${name}_cflags" $pkg_cflags && - set_sanitized "${name}_incdir" $pkg_incdir + set_sanitized "${name}_incflags" $pkg_incflags } check_pkg_config(){ @@ -1487,6 +1487,13 @@ check_pkg_config_cpp(){ eval add_cflags \$${name}_cflags } +check_pkg_config_header_only(){ + log check_pkg_config_cpp "$@" + name="$1" + test_pkg_config_cpp "$@" && + eval add_cflags \$${name}_incflags +} + test_exec(){ test_ld "cc" "$@" && { enabled cross_compile || $TMPE >> $logfile 2>&1; } } @@ -6842,7 +6849,7 @@ enabled vdpau && enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd if enabled vulkan; then - require_pkg_config_cpp vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || + check_pkg_config_header_only vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || require_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_2" fi From b3624069f05f1445ae75ba461e4e8ebc347ddf50 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 26 Nov 2021 17:10:56 +0800 Subject: [PATCH 264/894] avutil/hwcontext_vulkan: fully support customizable validation layers Validation layer is an indispensable part of developing on Vulkan. The following commands is on how to enable validation layers: ffmpeg -init_hw_device vulkan=0,debug=1,validation_layers=VK_LAYER_LUNARG_monitor+VK_LAYER_LUNARG_api_dump Signed-off-by: Wu Jianhua --- libavutil/hwcontext_vulkan.c | 164 ++++++++++++++++++++++++++++------- libavutil/vulkan_functions.h | 1 + 2 files changed, 136 insertions(+), 29 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 644ed947f8..1f952f2a80 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -146,6 +146,13 @@ typedef struct AVVkFrameInternal { } \ } while(0) +#define RELEASE_PROPS(props, count) \ + if (props) { \ + for (int i = 0; i < count; i++) \ + av_free((void *)((props)[i])); \ + av_free((void *)props); \ + } + static const struct { enum AVPixelFormat pixfmt; const VkFormat vkfmts[4]; @@ -511,25 +518,129 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, return 0; fail: - if (extension_names) - for (int i = 0; i < extensions_found; i++) - av_free((void *)extension_names[i]); - av_free(extension_names); + RELEASE_PROPS(extension_names, extensions_found); av_free(user_exts_str); av_free(sup_ext); return err; } +static int check_validation_layers(AVHWDeviceContext *ctx, AVDictionary *opts, + const char * const **dst, uint32_t *num, + int *debug_mode) +{ + static const char default_layer[] = { "VK_LAYER_KHRONOS_validation" }; + + int found = 0, err = 0; + VulkanDevicePriv *priv = ctx->internal->priv; + FFVulkanFunctions *vk = &priv->vkfn; + + uint32_t sup_layer_count; + VkLayerProperties *sup_layers; + + AVDictionaryEntry *user_layers; + char *user_layers_str = NULL; + char *save, *token; + + const char **enabled_layers = NULL; + uint32_t enabled_layers_count = 0; + + AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); + int debug = debug_opt && strtol(debug_opt->value, NULL, 10); + + /* If `debug=0`, enable no layers at all. */ + if (debug_opt && !debug) + return 0; + + vk->EnumerateInstanceLayerProperties(&sup_layer_count, NULL); + sup_layers = av_malloc_array(sup_layer_count, sizeof(VkLayerProperties)); + if (!sup_layers) + return AVERROR(ENOMEM); + vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers); + + av_log(ctx, AV_LOG_VERBOSE, "Supported validation layers:\n"); + for (int i = 0; i < sup_layer_count; i++) + av_log(ctx, AV_LOG_VERBOSE, "\t%s\n", sup_layers[i].layerName); + + /* If `debug=1` is specified, enable the standard validation layer extension */ + if (debug) { + *debug_mode = debug; + for (int i = 0; i < sup_layer_count; i++) { + if (!strcmp(default_layer, sup_layers[i].layerName)) { + found = 1; + av_log(ctx, AV_LOG_VERBOSE, "Default validation layer %s is enabled\n", + default_layer); + ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, default_layer); + break; + } + } + } + + user_layers = av_dict_get(opts, "validation_layers", NULL, 0); + if (!user_layers) + goto end; + + user_layers_str = av_strdup(user_layers->value); + if (!user_layers_str) { + err = AVERROR(EINVAL); + goto fail; + } + + token = av_strtok(user_layers_str, "+", &save); + while (token) { + found = 0; + if (!strcmp(default_layer, token)) { + if (debug) { + /* if the `debug=1`, default_layer is enabled, skip here */ + token = av_strtok(NULL, "+", &save); + continue; + } else { + /* if the `debug=0`, enable debug mode to load its callback properly */ + *debug_mode = debug; + } + } + for (int j = 0; j < sup_layer_count; j++) { + if (!strcmp(token, sup_layers[j].layerName)) { + found = 1; + break; + } + } + if (found) { + av_log(ctx, AV_LOG_VERBOSE, "Requested Validation Layer: %s\n", token); + ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token); + } else { + av_log(ctx, AV_LOG_ERROR, + "Validation Layer \"%s\" not support.\n", token); + err = AVERROR(EINVAL); + goto fail; + } + token = av_strtok(NULL, "+", &save); + } + + av_free(user_layers_str); + +end: + av_free(sup_layers); + + *dst = enabled_layers; + *num = enabled_layers_count; + + return 0; + +fail: + RELEASE_PROPS(enabled_layers, enabled_layers_count); + av_free(sup_layers); + av_free(user_layers_str); + return err; +} + /* Creates a VkInstance */ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) { - int err = 0; + int err = 0, debug_mode = 0; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); - const int debug_mode = debug_opt && strtol(debug_opt->value, NULL, 10); VkApplicationInfo application_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pEngineName = "libavutil", @@ -555,17 +666,18 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return err; } + err = check_validation_layers(ctx, opts, &inst_props.ppEnabledLayerNames, + &inst_props.enabledLayerCount, &debug_mode); + if (err) + goto fail; + /* Check for present/missing extensions */ err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames, &inst_props.enabledExtensionCount, debug_mode); + hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; + hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount; if (err < 0) - return err; - - if (debug_mode) { - static const char *layers[] = { "VK_LAYER_KHRONOS_validation" }; - inst_props.ppEnabledLayerNames = layers; - inst_props.enabledLayerCount = FF_ARRAY_ELEMS(layers); - } + goto fail; /* Try to create the instance */ ret = vk->CreateInstance(&inst_props, hwctx->alloc, &hwctx->inst); @@ -574,16 +686,14 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n", vk_ret2str(ret)); - for (int i = 0; i < inst_props.enabledExtensionCount; i++) - av_free((void *)inst_props.ppEnabledExtensionNames[i]); - av_free((void *)inst_props.ppEnabledExtensionNames); - return AVERROR_EXTERNAL; + err = AVERROR_EXTERNAL; + goto fail; } err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n"); - return err; + goto fail; } if (debug_mode) { @@ -604,10 +714,11 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) hwctx->alloc, &p->debug_ctx); } - hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; - hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount; + err = 0; - return 0; +fail: + RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount); + return err; } typedef struct VulkanDeviceSelection { @@ -1163,13 +1274,8 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) if (p->libvulkan) dlclose(p->libvulkan); - for (int i = 0; i < hwctx->nb_enabled_inst_extensions; i++) - av_free((void *)hwctx->enabled_inst_extensions[i]); - av_free((void *)hwctx->enabled_inst_extensions); - - for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) - av_free((void *)hwctx->enabled_dev_extensions[i]); - av_free((void *)hwctx->enabled_dev_extensions); + RELEASE_PROPS(hwctx->enabled_inst_extensions, hwctx->nb_enabled_inst_extensions); + RELEASE_PROPS(hwctx->enabled_dev_extensions, hwctx->nb_enabled_dev_extensions); } static int vulkan_device_create_internal(AVHWDeviceContext *ctx, diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 85a9f943c8..96922d7286 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -45,6 +45,7 @@ typedef enum FFVulkanExtensions { #define FN_LIST(MACRO) \ /* Instance */ \ MACRO(0, 0, FF_VK_EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, EnumerateInstanceLayerProperties) \ MACRO(0, 0, FF_VK_EXT_NO_FLAG, CreateInstance) \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyInstance) \ \ From 27c930002702f512b80124249c5efbcc0ef04841 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 24 Nov 2021 20:09:53 +0800 Subject: [PATCH 265/894] avformat/udp: remove local localaddr array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/udp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libavformat/udp.c b/libavformat/udp.c index bbe5aecc46..b8b0e19609 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -623,7 +623,7 @@ end: /* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) { - char hostname[1024], localaddr[1024] = ""; + char hostname[1024]; int port, udp_fd = -1, tmp, bind_ret = -1, dscp = -1; UDPContext *s = h->priv_data; int is_output; @@ -708,7 +708,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->burst_bits = strtoll(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { - av_strlcpy(localaddr, buf, sizeof(localaddr)); + av_freep(&s->localaddr); + s->localaddr = av_strdup(buf); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { if ((ret = ff_ip_parse_sources(h, buf, &s->filters)) < 0) @@ -748,10 +749,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) if ((s->is_multicast || s->local_port <= 0) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; - if (localaddr[0]) - udp_fd = udp_socket_create(h, &my_addr, &len, localaddr); - else - udp_fd = udp_socket_create(h, &my_addr, &len, s->localaddr); + udp_fd = udp_socket_create(h, &my_addr, &len, s->localaddr); if (udp_fd < 0) goto fail; From 9207dc3b0db368bb9cf5eb295cbc1129c2975e31 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 21 Nov 2021 01:57:41 +0100 Subject: [PATCH 266/894] avcodec/h263: Fix global-buffer-overflow with noout flag2 set h263_get_motion_length() forgot to take an absolute value; as a consequence, a negative index was used to access an array. This leads to potential crashes, but mostly it just accesses what is to the left of ff_mvtab (unless one uses ASAN), thereby defeating the purpose of the AV_CODEC_FLAG2_NO_OUTPUT because the sizes of the returned packets differ from the sizes the encoder would actually have produced. Signed-off-by: Andreas Rheinhardt --- libavcodec/h263.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/h263.h b/libavcodec/h263.h index 70fd1ffdc0..d6bef8318d 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -100,15 +100,16 @@ void ff_h263_encode_motion(PutBitContext *pb, int val, int f_code); static inline int h263_get_motion_length(int val, int f_code){ - int l, bit_size, code; + int bit_size, code, sign; if (val == 0) { return 1; /* ff_mvtab[0][1] */ } else { bit_size = f_code - 1; /* modulo encoding */ - l= INT_BIT - 6 - bit_size; - val = (val<>l; + val = sign_extend(val, 6 + bit_size); + sign = val >> 31; + val = (val ^ sign) - sign; /* val = FFABS(val) */ val--; code = (val >> bit_size) + 1; From 71204e8e3d0ae0b70dcac31ce3a984db79cd4eb0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 20 Nov 2021 17:00:48 +0100 Subject: [PATCH 267/894] Revert "Disable warnings for casting pointers to integers, there is nothing wrong with that." This reverts commit 5258f64a14713499cf84840b3ab3a1ee7cdcaeb8. The premise of said commit (that conversions from pointer to int are ok) is wrong: C99/C11 6.3.2.3 5: "Any pointer type may be converted to an integer type. [...] If the result cannot be represented in the integer type, the behavior is undefined." (C90 6.3.4 contains a similar restriction.) So don't disable -Wpointer-to-int-cast. Signed-off-by: Andreas Rheinhardt --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index e6cee21142..92cacbc1e7 100755 --- a/configure +++ b/configure @@ -6910,7 +6910,6 @@ check_cflags -Wwrite-strings check_cflags -Wtype-limits check_cflags -Wundef check_cflags -Wmissing-prototypes -check_cflags -Wno-pointer-to-int-cast check_cflags -Wstrict-prototypes check_cflags -Wempty-body From 81be19b90640c2989ab55e3e9c8a6c299aaa249b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 20 Nov 2021 12:14:55 +0100 Subject: [PATCH 268/894] fftools/ffmpeg: Take type limitations of AVFifo API into account The types used by the AVFifo API are inconsistent: av_fifo_(space|size)() returns an int; av_fifo_alloc() takes an unsigned, other parts use size_t. This commit therefore ensures that the size of the muxing_queue FIFO never exceeds INT_MAX. While just at it, also make sure not to call av_fifo_size() unnecessarily often. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 9 ++++----- fftools/ffmpeg_opt.c | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3761ea0c38..c838e2604c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -753,14 +753,13 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u AVPacket *tmp_pkt; /* the muxer is not initialized yet, buffer the packet */ if (!av_fifo_space(ost->muxing_queue)) { + size_t cur_size = av_fifo_size(ost->muxing_queue); unsigned int are_we_over_size = (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold; - int new_size = are_we_over_size ? - FFMIN(2 * av_fifo_size(ost->muxing_queue), - ost->max_muxing_queue_size) : - 2 * av_fifo_size(ost->muxing_queue); + size_t limit = are_we_over_size ? ost->max_muxing_queue_size : INT_MAX; + size_t new_size = FFMIN(2 * cur_size, limit); - if (new_size <= av_fifo_size(ost->muxing_queue)) { + if (new_size <= cur_size) { av_log(NULL, AV_LOG_ERROR, "Too many packets buffered for output stream %d:%d.\n", ost->file_index, ost->st->index); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index e55b584fd4..feed772452 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1613,6 +1613,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->max_muxing_queue_size = 128; MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); + ost->max_muxing_queue_size = FFMIN(ost->max_muxing_queue_size, INT_MAX / sizeof(ost->pkt)); ost->max_muxing_queue_size *= sizeof(ost->pkt); ost->muxing_queue_data_size = 0; From 7c2b9067d065a1ed503aa76ea82e5dd1763452dd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 20 Nov 2021 13:46:21 +0100 Subject: [PATCH 269/894] avformat/cafdec: Avoid unnecessary avio_tell() calls Signed-off-by: Andreas Rheinhardt --- libavformat/cafdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 3ff0558afe..4b5b15b58d 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -224,7 +224,7 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) av_log(s, AV_LOG_ERROR, "error reading packet table\n"); return AVERROR_INVALIDDATA; } - avio_skip(pb, ccount + size - avio_tell(pb)); + avio_seek(pb, ccount + size, SEEK_SET); caf->num_bytes = pos; return 0; @@ -331,7 +331,7 @@ static int read_header(AVFormatContext *s) if (size > 0 && (pb->seekable & AVIO_SEEKABLE_NORMAL)) { if (pos > INT64_MAX - size) return AVERROR_INVALIDDATA; - avio_skip(pb, FFMAX(0, pos + size - avio_tell(pb))); + avio_seek(pb, pos + size, SEEK_SET); } } From ff23cee200239a8368515c5d8ba94fc769c3fea2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 14 Nov 2021 18:09:17 +0100 Subject: [PATCH 270/894] avcodec/txd: Move input size checks before allocation Fixes: Timeout Fixes: 40882/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TXD_fuzzer-4893364584054784 Signed-off-by: Michael Niedermayer --- libavcodec/txd.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/libavcodec/txd.c b/libavcodec/txd.c index 86d60f3377..93e4fa9605 100644 --- a/libavcodec/txd.c +++ b/libavcodec/txd.c @@ -65,8 +65,26 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (depth == 8) { avctx->pix_fmt = AV_PIX_FMT_PAL8; - } else if (depth == 16 || depth == 32) { + if (bytestream2_get_bytes_left(&gb) < w * h + 4 * 256) + return AVERROR_INVALIDDATA; + } else if (depth == 16) { avctx->pix_fmt = AV_PIX_FMT_RGBA; + switch (d3d_format) { + case 0: + if (!(flags & 1)) + goto unsupported; + case TXD_DXT1: + if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8 + 4) + return AVERROR_INVALIDDATA; + break; + case TXD_DXT3: + if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16 + 4) + return AVERROR_INVALIDDATA; + } + } else if (depth == 32) { + avctx->pix_fmt = AV_PIX_FMT_RGBA; + if (bytestream2_get_bytes_left(&gb) < h * w * 4) + return AVERROR_INVALIDDATA; } else { avpriv_report_missing_feature(avctx, "Color depth of %u", depth); return AVERROR_PATCHWELCOME; @@ -92,8 +110,6 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, v = bytestream2_get_be32(&gb); pal[y] = (v >> 8) + (v << 24); } - if (bytestream2_get_bytes_left(&gb) < w * h) - return AVERROR_INVALIDDATA; bytestream2_skip(&gb, 4); for (y=0; yheight; j += 4) { for (i = 0; i < avctx->width; i += 4) { uint8_t *p = ptr + i * 4 + j * stride; @@ -117,8 +129,6 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } break; case TXD_DXT3: - if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16) - return AVERROR_INVALIDDATA; for (j = 0; j < avctx->height; j += 4) { for (i = 0; i < avctx->width; i += 4) { uint8_t *p = ptr + i * 4 + j * stride; @@ -134,8 +144,6 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, switch (d3d_format) { case 0x15: case 0x16: - if (bytestream2_get_bytes_left(&gb) < h * w * 4) - return AVERROR_INVALIDDATA; for (y=0; y Date: Sun, 14 Nov 2021 18:23:24 +0100 Subject: [PATCH 271/894] avformat/avidec: Check read_odml_index() for failure Fixes: Timeout Fixes: 40950/clusterfuzz-testcase-minimized-ffmpeg_dem_AVI_fuzzer-6478873068437504 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/avidec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/avidec.c b/libavformat/avidec.c index b10c3efa61..86f857b1e3 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -240,6 +240,8 @@ static int read_odml_index(AVFormatContext *s, int64_t frame_num) } else { int64_t offset, pos; int duration; + int ret; + offset = avio_rl64(pb); avio_rl32(pb); /* size */ duration = avio_rl32(pb); @@ -257,7 +259,7 @@ static int read_odml_index(AVFormatContext *s, int64_t frame_num) if (avio_seek(pb, offset + 8, SEEK_SET) < 0) return -1; avi->odml_depth++; - read_odml_index(s, frame_num); + ret = read_odml_index(s, frame_num); avi->odml_depth--; frame_num += duration; @@ -265,7 +267,8 @@ static int read_odml_index(AVFormatContext *s, int64_t frame_num) av_log(s, AV_LOG_ERROR, "Failed to restore position after reading index\n"); return -1; } - + if (ret < 0) + return ret; } } avi->index_loaded = 2; From 7bf4c06809296820f084fd5b3e362621ac99c3f4 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 26 Nov 2021 16:55:08 +0800 Subject: [PATCH 272/894] avformat/rtp: add localaddr for network interface selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- doc/protocols.texi | 4 ++++ libavformat/rtpproto.c | 17 ++++++++++++++--- libavformat/rtsp.c | 11 +++++++++++ libavformat/rtsp.h | 1 + 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index c100f23f17..d207df0b52 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1087,6 +1087,10 @@ set to 1) or to a default remote address (if set to 0). @item localport=@var{n} Set the local RTP port to @var{n}. +@item localaddr=@var{addr} +Local IP address of a network interface used for sending packets or joining +multicast groups. + @item timeout=@var{n} Set timeout (in microseconds) of socket I/O operations to @var{n}. diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 7dd6042158..c92cda63bb 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -61,6 +61,7 @@ typedef struct RTPContext { char *block; char *fec_options_str; int64_t rw_timeout; + char *localaddr; } RTPContext; #define OFFSET(x) offsetof(RTPContext, x) @@ -80,6 +81,7 @@ static const AVOption options[] = { { "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { "fec", "FEC", OFFSET(fec_options_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E }, + { "localaddr", "Local address", OFFSET(localaddr), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { NULL } }; @@ -173,6 +175,7 @@ static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const static void build_udp_url(RTPContext *s, char *buf, int buf_size, const char *hostname, + const char *localaddr, int port, int local_port, const char *include_sources, const char *exclude_sources) @@ -195,6 +198,8 @@ static void build_udp_url(RTPContext *s, url_add_option(buf, buf_size, "sources=%s", include_sources); if (exclude_sources && exclude_sources[0]) url_add_option(buf, buf_size, "block=%s", exclude_sources); + if (localaddr && localaddr[0]) + url_add_option(buf, buf_size, "localaddr=%s", localaddr); } /** @@ -284,6 +289,12 @@ static int rtp_open(URLContext *h, const char *uri, int flags) ff_ip_parse_blocks(h, s->block, &s->filters); block = s->block; } + if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { + av_freep(&s->localaddr); + s->localaddr = av_strdup(buf); + if (!s->localaddr) + goto fail; + } } if (s->rw_timeout >= 0) h->rw_timeout = s->rw_timeout; @@ -314,7 +325,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) for (i = 0; i < max_retry_count; i++) { build_udp_url(s, buf, sizeof(buf), - hostname, rtp_port, s->local_rtpport, + hostname, s->localaddr, rtp_port, s->local_rtpport, sources, block); if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0) @@ -328,7 +339,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) if (s->local_rtcpport < 0) { s->local_rtcpport = s->local_rtpport + 1; build_udp_url(s, buf, sizeof(buf), - hostname, s->rtcp_port, s->local_rtcpport, + hostname, s->localaddr, s->rtcp_port, s->local_rtcpport, sources, block); if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback, NULL, @@ -339,7 +350,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) break; } build_udp_url(s, buf, sizeof(buf), - hostname, s->rtcp_port, s->local_rtcpport, + hostname, s->localaddr, s->rtcp_port, s->local_rtcpport, sources, block); if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index a1aa969cad..e6a4993acd 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -105,6 +105,7 @@ static const AVOption sdp_options[] = { { "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" }, { "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" }, { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC }, + { "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), COMMON_OPTS(), { NULL }, @@ -113,6 +114,7 @@ static const AVOption sdp_options[] = { static const AVOption rtp_options[] = { RTSP_FLAG_OPTS("rtp_flags", "set RTP flags"), { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC }, + { "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), COMMON_OPTS(), { NULL }, @@ -125,6 +127,8 @@ static AVDictionary *map_to_opts(RTSPState *rt) av_dict_set_int(&opts, "buffer_size", rt->buffer_size, 0); av_dict_set_int(&opts, "pkt_size", rt->pkt_size, 0); + if (rt->localaddr && rt->localaddr[0]) + av_dict_set(&opts, "localaddr", rt->localaddr, 0); return opts; } @@ -2407,6 +2411,8 @@ static int sdp_read_header(AVFormatContext *s) if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) { AVDictionary *opts = map_to_opts(rt); + char buf[MAX_URL_SIZE]; + const char *p; err = getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), @@ -2424,6 +2430,11 @@ static int sdp_read_header(AVFormatContext *s) rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0, rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0); + p = strchr(s->url, '?'); + if (p && av_find_info_tag(buf, sizeof(buf), "localaddr", p)) + av_strlcatf(url, sizeof(url), "&localaddr=%s", buf); + else if (rt->localaddr && rt->localaddr[0]) + av_strlcatf(url, sizeof(url), "&localaddr=%s", rt->localaddr); append_source_addrs(url, sizeof(url), "sources", rtsp_st->nb_include_source_addrs, rtsp_st->include_source_addrs); diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 4ec974ed73..d6fdfe069c 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -419,6 +419,7 @@ typedef struct RTSPState { char default_lang[4]; int buffer_size; int pkt_size; + char *localaddr; } RTSPState; #define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets - From 33be4e6ca904201afe8fb99ee245586bb477b40e Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 27 Nov 2021 04:37:39 +0100 Subject: [PATCH 273/894] configure: fix test_pkg_config_cpp after 1e5acc1b5985c58e --- configure | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 92cacbc1e7..4af36bf80a 100755 --- a/configure +++ b/configure @@ -1464,12 +1464,14 @@ test_pkg_config_cpp(){ cond="$4" shift 4 disable $name - test_cmd $pkg_config --exists --print-errors $pkg_version || returnddd + test_cmd $pkg_config --exists --print-errors $pkg_version || return pkg_cflags=$($pkg_config --cflags $pkg_config_flags $pkg) - pkg_incflags=$($pkg_config --cflags-onyl-I $pkg_config_flags $pkg) + pkg_incdir=$($pkg_config --variable=includedir $pkg_config_flags $pkg) + pkg_incflags=$($pkg_config --cflags-only-I $pkg_config_flags $pkg) test_cpp_condition "$pkg_incdir/$headers" "$cond" "$@" && enable $name && set_sanitized "${name}_cflags" $pkg_cflags && + set_sanitized "${name}_incdir" $pkg_incdir && set_sanitized "${name}_incflags" $pkg_incflags } From c90b3661fadcec98ab6462ac9f8180aa0cb8ec62 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 27 Nov 2021 04:38:27 +0100 Subject: [PATCH 274/894] hwcontext_vulkan: use correct return value for allocation failure --- libavutil/hwcontext_vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 1f952f2a80..a0437c9661 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -581,7 +581,7 @@ static int check_validation_layers(AVHWDeviceContext *ctx, AVDictionary *opts, user_layers_str = av_strdup(user_layers->value); if (!user_layers_str) { - err = AVERROR(EINVAL); + err = AVERROR(ENOMEM); goto fail; } From a5ee1663270cd15fa4d5f40d384a8d9eab4f7218 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 21:48:49 +0100 Subject: [PATCH 275/894] avformat/avformat: Add AVStream parameter to check_bitstream() sig For most check_bitstream() functions this just avoids having to dereference s->streams[pkt->stream_index] themselves; but for meta-muxers it will allow to forward the packet to stream with a different stream_index (belonging to a different AVFormatContext) without using a spare packet. Signed-off-by: Andreas Rheinhardt --- libavformat/avformat.h | 7 ++++++- libavformat/dashenc.c | 12 +++++++----- libavformat/flvenc.c | 4 ++-- libavformat/latmenc.c | 4 ++-- libavformat/matroskaenc.c | 4 ++-- libavformat/movenc.c | 4 ++-- libavformat/mpegtsenc.c | 4 ++-- libavformat/mux.c | 2 +- libavformat/rawenc.c | 12 ++++++------ libavformat/segment.c | 10 ++++++---- 10 files changed, 36 insertions(+), 27 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 0343825aa0..75699f3a32 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -322,6 +322,7 @@ #include "libavformat/version.h" struct AVFormatContext; +struct AVStream; struct AVDeviceInfoList; struct AVDeviceCapabilitiesQuery; @@ -623,9 +624,13 @@ typedef struct AVOutputFormat { /** * Set up any necessary bitstream filtering and extract any extra data needed * for the global header. + * + * @note pkt might have been directly forwarded by a meta-muxer; therefore + * pkt->stream_index as well as the pkt's timebase might be invalid. * Return 0 if more packets from this stream must be checked; 1 if not. */ - int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt); + int (*check_bitstream)(struct AVFormatContext *s, struct AVStream *st, + const AVPacket *pkt); } AVOutputFormat; /** * @} diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 5faf06e11d..dd2b34afbb 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -2333,19 +2333,21 @@ static int dash_write_trailer(AVFormatContext *s) return 0; } -static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt) +static int dash_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *avpkt) { DASHContext *c = s->priv_data; - OutputStream *os = &c->streams[avpkt->stream_index]; + OutputStream *os = &c->streams[st->index]; AVFormatContext *oc = os->ctx; if (oc->oformat->check_bitstream) { + AVStream *const ost = oc->streams[0]; int ret; AVPacket pkt = *avpkt; pkt.stream_index = 0; - ret = oc->oformat->check_bitstream(oc, &pkt); + ret = oc->oformat->check_bitstream(oc, ost, &pkt); if (ret == 1) { - FFStream *const sti = ffstream(s->streams[avpkt->stream_index]); - FFStream *const osti = ffstream(oc->streams[0]); + FFStream *const sti = ffstream(st); + FFStream *const osti = ffstream(ost); sti->bsfc = osti->bsfc; osti->bsfc = NULL; } diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 3f24c7e192..c5926575a1 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -1083,10 +1083,10 @@ fail: return ret; } -static int flv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int flv_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index 21bb614f67..72865c9565 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -245,10 +245,10 @@ too_large: return AVERROR_INVALIDDATA; } -static int latm_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int latm_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 6945c26f5a..f08ead0a96 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2731,10 +2731,10 @@ static int mkv_init(struct AVFormatContext *s) return 0; } -static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int mkv_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 233aee62d4..9886bc7b64 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -7343,10 +7343,10 @@ static int mov_write_trailer(AVFormatContext *s) return res; } -static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int mov_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index e3fba54939..79ec1a7e5f 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -2208,10 +2208,10 @@ static void mpegts_deinit(AVFormatContext *s) av_freep(&ts->services); } -static int mpegts_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int mpegts_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_H264) { if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && diff --git a/libavformat/mux.c b/libavformat/mux.c index 1389bcc003..d93dc73f8e 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -1074,7 +1074,7 @@ static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) if (s->oformat->check_bitstream) { if (!sti->bitstream_checked) { - if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) + if ((ret = s->oformat->check_bitstream(s, &sti->pub, pkt)) < 0) return ret; else if (ret == 1) sti->bitstream_checked = 1; diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 15e7051873..4bbae7717b 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -341,9 +341,9 @@ const AVOutputFormat ff_h263_muxer = { #endif #if CONFIG_H264_MUXER -static int h264_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int h264_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { - AVStream *st = s->streams[0]; if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && AV_RB24(pkt->data) != 0x000001) return ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL); @@ -364,9 +364,9 @@ const AVOutputFormat ff_h264_muxer = { #endif #if CONFIG_HEVC_MUXER -static int hevc_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int hevc_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { - AVStream *st = s->streams[0]; if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && AV_RB24(pkt->data) != 0x000001) return ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL); @@ -468,9 +468,9 @@ const AVOutputFormat ff_mpeg2video_muxer = { #endif #if CONFIG_OBU_MUXER -static int obu_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int obu_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { - AVStream *st = s->streams[0]; return ff_stream_add_bitstream_filter(st, "av1_metadata", "td=insert"); } diff --git a/libavformat/segment.c b/libavformat/segment.c index 2b024fd373..9861462405 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -984,15 +984,17 @@ static int seg_write_trailer(struct AVFormatContext *s) return ret; } -static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int seg_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; if (oc->oformat->check_bitstream) { - int ret = oc->oformat->check_bitstream(oc, pkt); + AVStream *const ost = oc->streams[st->index]; + int ret = oc->oformat->check_bitstream(oc, ost, pkt); if (ret == 1) { - FFStream *const sti = ffstream( s->streams[pkt->stream_index]); - FFStream *const osti = ffstream(oc->streams[pkt->stream_index]); + FFStream *const sti = ffstream(st); + FFStream *const osti = ffstream(ost); sti->bsfc = osti->bsfc; osti->bsfc = NULL; } From 5e01fc83181edb0bccc480f3c7f48ea928d8e444 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 22:12:40 +0100 Subject: [PATCH 276/894] avformat/dashenc: Don't use stack packet Signed-off-by: Andreas Rheinhardt --- libavformat/dashenc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index dd2b34afbb..3f28f5ad71 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -2342,9 +2342,7 @@ static int dash_check_bitstream(AVFormatContext *s, AVStream *st, if (oc->oformat->check_bitstream) { AVStream *const ost = oc->streams[0]; int ret; - AVPacket pkt = *avpkt; - pkt.stream_index = 0; - ret = oc->oformat->check_bitstream(oc, ost, &pkt); + ret = oc->oformat->check_bitstream(oc, ost, avpkt); if (ret == 1) { FFStream *const sti = ffstream(st); FFStream *const osti = ffstream(ost); From a81e0ee21f64213e750ccb10128775337c73431d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 23:05:27 +0100 Subject: [PATCH 277/894] avformat/movenc: Avoid allocation of AVPacket Signed-off-by: Andreas Rheinhardt --- libavformat/movenc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 9886bc7b64..38ff90833a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6458,8 +6458,6 @@ static void mov_free(AVFormatContext *s) MOVMuxContext *mov = s->priv_data; int i; - av_packet_free(&mov->pkt); - if (!mov->tracks) return; @@ -6569,6 +6567,7 @@ static int mov_init(AVFormatContext *s) int i, ret; mov->fc = s; + mov->pkt = ffformatcontext(s)->pkt; /* Default mode == MP4 */ mov->mode = MODE_MP4; @@ -6714,10 +6713,6 @@ static int mov_init(AVFormatContext *s) mov->nb_streams += mov->nb_meta_tmcd; } - mov->pkt = av_packet_alloc(); - if (!mov->pkt) - return AVERROR(ENOMEM); - // Reserve an extra stream for chapters for the case where chapters // are written in the trailer mov->tracks = av_calloc(mov->nb_streams + 1, sizeof(*mov->tracks)); From 2cddb2f7a8a98408e3f238933ebf1ae7280fa5fd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 23:16:12 +0100 Subject: [PATCH 278/894] avformat/mpegtsenc: Avoid allocation of AVPacket Signed-off-by: Andreas Rheinhardt --- libavformat/mpegtsenc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 79ec1a7e5f..92b4cc8087 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1140,9 +1140,7 @@ static int mpegts_init(AVFormatContext *s) ts->nit.write_packet = section_write_packet; ts->nit.opaque = s; - ts->pkt = av_packet_alloc(); - if (!ts->pkt) - return AVERROR(ENOMEM); + ts->pkt = ffformatcontext(s)->pkt; /* assign pids to each stream */ for (i = 0; i < s->nb_streams; i++) { @@ -2186,8 +2184,6 @@ static void mpegts_deinit(AVFormatContext *s) MpegTSService *service; int i; - av_packet_free(&ts->pkt); - for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; MpegTSWriteStream *ts_st = st->priv_data; From cd0bdce71ac0b9871fa04d31756daa26fa7999af Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Thu, 25 Nov 2021 14:30:33 -0500 Subject: [PATCH 279/894] avcodec/mjpeg_parser: skip markers after EOI, not by size The check for m->size >= 0xF000 is intended to avoid skipping too much garbage data between JPEG frames in test_roman (thus missing next SOI), but it erroneously also skips valid markers between SOI and SOS. Instead of this, we should simply skip parsing markers other than SOI after EOI. That way, we will not accidentally skip over SOI due to some garbage between frames. There is still a small risk of encountering FFD8 in the garbage data, but the chance of this is fairly low. Fixes: https://trac.ffmpeg.org/ticket/8967 Signed-off-by: Michael Niedermayer --- libavcodec/mjpeg_parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpeg_parser.c b/libavcodec/mjpeg_parser.c index 16a5902c7c..62b923b625 100644 --- a/libavcodec/mjpeg_parser.c +++ b/libavcodec/mjpeg_parser.c @@ -80,10 +80,10 @@ static int find_frame_end(MJPEGParserContext *m, const uint8_t *buf, int buf_siz pc->frame_start_found=0; pc->state=0; return i-3; + } else if((state>>16)==0xFFD9 && (state&0xFFFF)!=0xFFD8){ + state= 0xFFD900|(state&0xFF); } else if(state<0xFFD00000 || state>0xFFD9FFFF){ m->size= (state&0xFFFF)-1; - if (m->size >= 0xF000) - m->size = 0; } } if(m->size>0){ From 6fdd7fe0b89f5f76314bf06a7d28fb18d0196f84 Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Thu, 25 Nov 2021 14:36:46 -0500 Subject: [PATCH 280/894] avformat/img2dec: probe JFIF/Exif header Due to reasons, mpv doesn't pass filename when probing. mpv also sets default probescore threshold to 26. Since the current jpeg_probe implementation returns 25 until EOI, it means that the whole image needs to be probed to succeed. Worse, the whole image is not passed at once; increasingly large buffers are tried before that. Adding it up together, if many demuxers are enabled, moderately large JPEG files (few MB) can take several seconds to open, despite taking less than 1 second to actually decode. Therefore, adjust the heuristic to be more optimistic if proper JFIF or Exif segments are found. While not strictly required, the vast majority of JPEG-ish files have one or the other or both. Signed-off-by: Michael Niedermayer --- libavformat/img2dec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index b535831e1c..a6084ceef0 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -749,7 +749,7 @@ static int j2k_probe(const AVProbeData *p) static int jpeg_probe(const AVProbeData *p) { const uint8_t *b = p->buf; - int i, state = SOI; + int i, state = SOI, got_header = 0; if (AV_RB16(b) != 0xFFD8 || AV_RB32(b) == 0xFFD8FFF7) @@ -789,7 +789,11 @@ static int jpeg_probe(const AVProbeData *p) break; case DQT: case APP0: + if (AV_RL32(&b[i + 4]) == MKTAG('J','F','I','F')) + got_header = 1; case APP1: + if (AV_RL32(&b[i + 4]) == MKTAG('E','x','i','f')) + got_header = 1; case APP2: case APP3: case APP4: @@ -817,7 +821,7 @@ static int jpeg_probe(const AVProbeData *p) if (state == EOI) return AVPROBE_SCORE_EXTENSION + 1; if (state == SOS) - return AVPROBE_SCORE_EXTENSION / 2; + return AVPROBE_SCORE_EXTENSION / 2 + got_header; return AVPROBE_SCORE_EXTENSION / 8 + 1; } From f5e74e8d484af23e760e1d4ce292b3a983e0b181 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 27 Nov 2021 14:54:26 +0100 Subject: [PATCH 281/894] avfilter/vf_paletteuse: Add missing parentheses Fixes a mistake in dea673d0d548c864ec85f9260d8900d944ef7a2a. GCC emitted a -Wint-in-bool-context warning because of that. Reviewed-by: Soft Works Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_paletteuse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 5f20cd75b2..5b300be5a5 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -811,7 +811,7 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, uint8_t *src2 = in2->data[0]; const int src1_linesize = in1->linesize[0] >> 2; const int src2_linesize = in2->linesize[0]; - const float div = in1->width * in1->height * s->use_alpha ? 4 : 3; + const float div = in1->width * in1->height * (s->use_alpha ? 4 : 3); unsigned mean_err = 0; for (y = 0; y < in1->height; y++) { From d6c16c5217a8d2cbb754d44bf1206479fe5f906d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 08:22:38 +0100 Subject: [PATCH 282/894] avcodec/mobiclip: Rewrite code to make it clearer In order to know that the earlier code did not use uninitialized values one needs to know that the lowest four bits of each used value of pframe_block4x4_coefficients_tab do not vanish identically. E.g. Coverity did not get this and warned about it in ticket #1466632. Fix this by slightly rewriting the code. Signed-off-by: Andreas Rheinhardt --- libavcodec/mobiclip.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/mobiclip.c b/libavcodec/mobiclip.c index 6ea1c3eefa..23d64f76f6 100644 --- a/libavcodec/mobiclip.c +++ b/libavcodec/mobiclip.c @@ -491,7 +491,7 @@ static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, int ret, idx = get_ue_golomb_31(gb); if (idx == 0) { - ret = add_coefficients(avctx, frame, bx, by, size, plane); + return add_coefficients(avctx, frame, bx, by, size, plane); } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) { int flags = pframe_block4x4_coefficients_tab[idx]; @@ -505,11 +505,10 @@ static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, flags >>= 1; } } + return 0; } else { - ret = AVERROR_INVALIDDATA; + return AVERROR_INVALIDDATA; } - - return ret; } static int adjust(int x, int size) From 5593f5cf242a99495b6047e5c226bfe4b934342e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 26 Nov 2021 20:17:09 +0100 Subject: [PATCH 283/894] avcodec/vqavideo: Remove dead code Fixes Coverity issue #1493344. Signed-off-by: Andreas Rheinhardt --- libavcodec/vqavideo.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 5466e25cdf..61f0a2c950 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -692,11 +692,6 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) bytestream2_get_buffer(&s->gb, s->codebook, chunk_size); } - if (vprz_chunk == -1 && vptr_chunk == -1) { - av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n"); - return AVERROR_INVALIDDATA; - } - /* decode the frame */ if (vptr_chunk != -1) { @@ -716,7 +711,7 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0) return res; } else { - av_log(s->avctx, AV_LOG_ERROR, "expected either VPTR or VPRZ chunk\n"); + av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n"); return AVERROR_INVALIDDATA; } From 4b54818981d2783af161c2ff670b658afbdda503 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 15:39:44 -0600 Subject: [PATCH 284/894] ffmpeg: remove ffmpeg_videotoolbox This was almost completely redundant. The only functionality that's no longer available after this removal is the videotoolbox_pixfmt arg, which has been obsolete for several years. --- fftools/Makefile | 4 - fftools/ffmpeg.c | 37 +------ fftools/ffmpeg.h | 10 -- fftools/ffmpeg_opt.c | 28 +----- fftools/ffmpeg_videotoolbox.c | 177 ---------------------------------- 5 files changed, 7 insertions(+), 249 deletions(-) delete mode 100644 fftools/ffmpeg_videotoolbox.c diff --git a/fftools/Makefile b/fftools/Makefile index 5234932ab0..da420786eb 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -10,10 +10,6 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF)) ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) OBJS-ffmpeg += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o -ifndef CONFIG_VIDEOTOOLBOX -OBJS-ffmpeg-$(CONFIG_VDA) += fftools/ffmpeg_videotoolbox.o -endif -OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += fftools/ffmpeg_videotoolbox.o define DOFFTOOL OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c838e2604c..25360423b5 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2858,12 +2858,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat break; } } - if (config) { - if (config->device_type != ist->hwaccel_device_type) { - // Different hwaccel offered, ignore. - continue; - } - + if (config && config->device_type == ist->hwaccel_device_type) { ret = hwaccel_decode_init(s); if (ret < 0) { if (ist->hwaccel_id == HWACCEL_GENERIC) { @@ -2876,36 +2871,10 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } continue; } - } else { - const HWAccel *hwaccel = NULL; - int i; - for (i = 0; hwaccels[i].name; i++) { - if (hwaccels[i].pix_fmt == *p) { - hwaccel = &hwaccels[i]; - break; - } - } - if (!hwaccel) { - // No hwaccel supporting this pixfmt. - continue; - } - if (hwaccel->id != ist->hwaccel_id) { - // Does not match requested hwaccel. - continue; - } - ret = hwaccel->init(s); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, - "%s hwaccel requested for input stream #%d:%d, " - "but cannot be initialized.\n", hwaccel->name, - ist->file_index, ist->st->index); - return AV_PIX_FMT_NONE; - } + ist->hwaccel_pix_fmt = *p; + break; } - - ist->hwaccel_pix_fmt = *p; - break; } return *p; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 1728010f56..21c63415d6 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -60,16 +60,8 @@ enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, HWACCEL_GENERIC, - HWACCEL_VIDEOTOOLBOX, }; -typedef struct HWAccel { - const char *name; - int (*init)(AVCodecContext *s); - enum HWAccelID id; - enum AVPixelFormat pix_fmt; -} HWAccel; - typedef struct HWDevice { const char *name; enum AVHWDeviceType type; @@ -626,7 +618,6 @@ extern int stdin_interaction; extern int frame_bits_per_raw_sample; extern AVIOContext *progress_avio; extern float max_error_rate; -extern char *videotoolbox_pixfmt; extern char *filter_nbthreads; extern int filter_complex_nbthreads; @@ -636,7 +627,6 @@ extern int auto_conversion_filters; extern const AVIOInterruptCB int_cb; extern const OptionDef options[]; -extern const HWAccel hwaccels[]; #if CONFIG_QSV extern char *qsv_device; #endif diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index feed772452..debd13f3bd 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -134,12 +134,6 @@ static const char *const opt_name_enc_time_bases[] = {"enc_time_base" }\ } -const HWAccel hwaccels[] = { -#if CONFIG_VIDEOTOOLBOX - { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, -#endif - { 0 }, -}; HWDevice *filter_hw_device; char *vstats_filename; @@ -931,21 +925,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) else if (!strcmp(hwaccel, "auto")) ist->hwaccel_id = HWACCEL_AUTO; else { - enum AVHWDeviceType type; - int i; - for (i = 0; hwaccels[i].name; i++) { - if (!strcmp(hwaccels[i].name, hwaccel)) { - ist->hwaccel_id = hwaccels[i].id; - break; - } - } - - if (!ist->hwaccel_id) { - type = av_hwdevice_find_type_by_name(hwaccel); - if (type != AV_HWDEVICE_TYPE_NONE) { - ist->hwaccel_id = HWACCEL_GENERIC; - ist->hwaccel_device_type = type; - } + enum AVHWDeviceType type = av_hwdevice_find_type_by_name(hwaccel); + if (type != AV_HWDEVICE_TYPE_NONE) { + ist->hwaccel_id = HWACCEL_GENERIC; + ist->hwaccel_device_type = type; } if (!ist->hwaccel_id) { @@ -3811,9 +3794,6 @@ const OptionDef options[] = { { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, "select output format used with HW accelerated decoding", "format" }, -#if CONFIG_VIDEOTOOLBOX - { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, -#endif { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, "show available HW acceleration methods" }, { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC | diff --git a/fftools/ffmpeg_videotoolbox.c b/fftools/ffmpeg_videotoolbox.c deleted file mode 100644 index 4ba8618539..0000000000 --- a/fftools/ffmpeg_videotoolbox.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#if HAVE_UTGETOSTYPEFROMSTRING -#include -#endif - -#include "libavcodec/avcodec.h" -#include "libavcodec/videotoolbox.h" -#include "libavutil/imgutils.h" -#include "ffmpeg.h" - -typedef struct VTContext { - AVFrame *tmp_frame; - int log_once; -} VTContext; - -char *videotoolbox_pixfmt; - -static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame) -{ - InputStream *ist = s->opaque; - VTContext *vt = ist->hwaccel_ctx; - CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3]; - OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); - CVReturn err; - uint8_t *data[4] = { 0 }; - int linesize[4] = { 0 }; - int planes, ret, i; - - if (frame->format == ist->hwaccel_output_format) { - av_log_once(s, AV_LOG_INFO, AV_LOG_TRACE, &vt->log_once, - "There is no video filter for videotoolbox pix_fmt now, remove the " - "-hwaccel_output_format option if video filter doesn't work\n"); - return 0; - } - - av_frame_unref(vt->tmp_frame); - - switch (pixel_format) { - case kCVPixelFormatType_420YpCbCr8Planar: vt->tmp_frame->format = AV_PIX_FMT_YUV420P; break; - case kCVPixelFormatType_422YpCbCr8: vt->tmp_frame->format = AV_PIX_FMT_UYVY422; break; - case kCVPixelFormatType_32BGRA: vt->tmp_frame->format = AV_PIX_FMT_BGRA; break; -#ifdef kCFCoreFoundationVersionNumber10_7 - case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break; -#endif -#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE - case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: vt->tmp_frame->format = AV_PIX_FMT_P010; break; -#endif - default: - av_log(NULL, AV_LOG_ERROR, - "%s: Unsupported pixel format: %s\n", - av_fourcc2str(s->codec_tag), videotoolbox_pixfmt); - return AVERROR(ENOSYS); - } - - vt->tmp_frame->width = frame->width; - vt->tmp_frame->height = frame->height; - ret = av_frame_get_buffer(vt->tmp_frame, 0); - if (ret < 0) - return ret; - - err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); - if (err != kCVReturnSuccess) { - av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n"); - return AVERROR_UNKNOWN; - } - - if (CVPixelBufferIsPlanar(pixbuf)) { - - planes = CVPixelBufferGetPlaneCount(pixbuf); - for (i = 0; i < planes; i++) { - data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); - linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); - } - } else { - data[0] = CVPixelBufferGetBaseAddress(pixbuf); - linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf); - } - - av_image_copy(vt->tmp_frame->data, vt->tmp_frame->linesize, - (const uint8_t **)data, linesize, vt->tmp_frame->format, - frame->width, frame->height); - - ret = av_frame_copy_props(vt->tmp_frame, frame); - CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); - if (ret < 0) - return ret; - - av_frame_unref(frame); - av_frame_move_ref(frame, vt->tmp_frame); - - return 0; -} - -static void videotoolbox_uninit(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - VTContext *vt = ist->hwaccel_ctx; - - ist->hwaccel_uninit = NULL; - ist->hwaccel_retrieve_data = NULL; - - av_frame_free(&vt->tmp_frame); - - av_videotoolbox_default_free(s); - av_freep(&ist->hwaccel_ctx); -} - -int videotoolbox_init(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - int ret = 0; - VTContext *vt; - - vt = av_mallocz(sizeof(*vt)); - if (!vt) - return AVERROR(ENOMEM); - - ist->hwaccel_ctx = vt; - ist->hwaccel_uninit = videotoolbox_uninit; - ist->hwaccel_retrieve_data = videotoolbox_retrieve_data; - - vt->tmp_frame = av_frame_alloc(); - if (!vt->tmp_frame) { - ret = AVERROR(ENOMEM); - goto fail; - } - - // TODO: reindent - if (!videotoolbox_pixfmt) { - ret = av_videotoolbox_default_init(s); - } else { - AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context(); - CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault, - videotoolbox_pixfmt, - kCFStringEncodingUTF8); -#if HAVE_UTGETOSTYPEFROMSTRING - vtctx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str); -#else - av_log(s, loglevel, "UTGetOSTypeFromString() is not available " - "on this platform, %s pixel format can not be honored from " - "the command line\n", videotoolbox_pixfmt); -#endif - ret = av_videotoolbox_default_init2(s, vtctx); - CFRelease(pixfmt_str); - } - if (ret < 0) { - av_log(NULL, loglevel, "Error creating Videotoolbox decoder.\n"); - goto fail; - } - - return 0; -fail: - videotoolbox_uninit(s); - return ret; -} From b2cd1fb2ec64d04841d6c06fddf6e1d6e4ecfb34 Mon Sep 17 00:00:00 2001 From: rcombs Date: Fri, 12 Nov 2021 23:50:17 -0600 Subject: [PATCH 285/894] lavu/pixfmt: add high-bit-depth semi-planar 4:2:2/4:4:4 formats These are used by VideoToolbox hardware decoders. --- doc/APIchanges | 3 + libavutil/pixdesc.c | 96 ++++++++++++++++++++++++++++++++ libavutil/pixfmt.h | 18 ++++++ tests/ref/fate/imgutils | 8 +++ tests/ref/fate/sws-pixdesc-query | 44 +++++++++++++++ 5 files changed, 169 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 565f7e091e..bc9f4e38da 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-11-22 - xxxxxxxxxx - lavu 57.9.100 - pixfmt.h + Add AV_PIX_FMT_P210, AV_PIX_FMT_P410, AV_PIX_FMT_P216, and AV_PIX_FMT_P416. + 2021-11-17 - xxxxxxxxxx - lavf 57.9.100 - frame.h Add AV_FRAME_DATA_DOVI_RPU_BUFFER. diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 69cb198646..727d7540b3 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -2393,6 +2393,102 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "vulkan", .flags = AV_PIX_FMT_FLAG_HWACCEL, }, + [AV_PIX_FMT_P210BE] = { + .name = "p210be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P210LE] = { + .name = "p210le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P410BE] = { + .name = "p410be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P410LE] = { + .name = "p410le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P216BE] = { + .name = "p216be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P216LE] = { + .name = "p216le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P416BE] = { + .name = "p416be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P416LE] = { + .name = "p416le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, }; static const char * const color_range_names[] = { diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 53bdecfcb7..02e355eb4d 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -352,6 +352,19 @@ enum AVPixelFormat { AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined + + AV_PIX_FMT_P210BE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_P210LE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_P410BE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian + AV_PIX_FMT_P410LE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian + + AV_PIX_FMT_P216BE, ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian + AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, liddle-endian + + AV_PIX_FMT_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian + AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; @@ -444,6 +457,11 @@ enum AVPixelFormat { #define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) #define AV_PIX_FMT_X2BGR10 AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE) +#define AV_PIX_FMT_P210 AV_PIX_FMT_NE(P210BE, P210LE) +#define AV_PIX_FMT_P410 AV_PIX_FMT_NE(P410BE, P410LE) +#define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) +#define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) + /** * Chromaticity coordinates of the source primaries. * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273. diff --git a/tests/ref/fate/imgutils b/tests/ref/fate/imgutils index 495bbd46f0..b23d1b4c39 100644 --- a/tests/ref/fate/imgutils +++ b/tests/ref/fate/imgutils @@ -238,3 +238,11 @@ x2rgb10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 x2rgb10be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 x2bgr10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 x2bgr10be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +p210be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p210le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p410be planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p410le planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p216be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p216le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p416be planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p416le planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query index a74109c3d7..553c039061 100644 --- a/tests/ref/fate/sws-pixdesc-query +++ b/tests/ref/fate/sws-pixdesc-query @@ -13,6 +13,10 @@ is16BPS: gray16le p016be p016le + p216be + p216le + p416be + p416le rgb48be rgb48le rgba64be @@ -57,6 +61,10 @@ isNBPS: nv20le p010be p010le + p210be + p210le + p410be + p410le x2bgr10be x2bgr10le x2rgb10be @@ -140,6 +148,10 @@ isBE: nv20be p010be p016be + p210be + p216be + p410be + p416be rgb444be rgb48be rgb555be @@ -193,6 +205,14 @@ isYUV: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le uyvy422 uyyvyy411 xyz12be @@ -287,6 +307,14 @@ isPlanarYUV: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le yuv410p yuv411p yuv420p @@ -370,6 +398,14 @@ isSemiPlanarYUV: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le isRGB: 0bgr @@ -751,6 +787,14 @@ Planar: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le yuv410p yuv411p yuv420p From f0204de47d30e40b3f954fa0a15d76a48bcb5afd Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 13:34:21 -0600 Subject: [PATCH 286/894] swscale: add P210/P410/P216/P416 input --- libswscale/input.c | 16 ++++++++++++++++ libswscale/utils.c | 8 ++++++++ libswscale/version.h | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libswscale/input.c b/libswscale/input.c index 1351ea5bd4..6acc39f89f 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -1238,15 +1238,23 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->chrToYV12 = read_ayuv64le_UV_c; break; case AV_PIX_FMT_P010LE: + case AV_PIX_FMT_P210LE: + case AV_PIX_FMT_P410LE: c->chrToYV12 = p010LEToUV_c; break; case AV_PIX_FMT_P010BE: + case AV_PIX_FMT_P210BE: + case AV_PIX_FMT_P410BE: c->chrToYV12 = p010BEToUV_c; break; case AV_PIX_FMT_P016LE: + case AV_PIX_FMT_P216LE: + case AV_PIX_FMT_P416LE: c->chrToYV12 = p016LEToUV_c; break; case AV_PIX_FMT_P016BE: + case AV_PIX_FMT_P216BE: + case AV_PIX_FMT_P416BE: c->chrToYV12 = p016BEToUV_c; break; case AV_PIX_FMT_Y210LE: @@ -1519,6 +1527,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GRAY16LE: case AV_PIX_FMT_P016LE: + case AV_PIX_FMT_P216LE: + case AV_PIX_FMT_P416LE: c->lumToYV12 = bswap16Y_c; break; case AV_PIX_FMT_YUVA420P9LE: @@ -1561,6 +1571,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GRAY16BE: case AV_PIX_FMT_P016BE: + case AV_PIX_FMT_P216BE: + case AV_PIX_FMT_P416BE: c->lumToYV12 = bswap16Y_c; break; case AV_PIX_FMT_YUVA420P9BE: @@ -1687,9 +1699,13 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->lumToYV12 = bgr64LEToY_c; break; case AV_PIX_FMT_P010LE: + case AV_PIX_FMT_P210LE: + case AV_PIX_FMT_P410LE: c->lumToYV12 = p010LEToY_c; break; case AV_PIX_FMT_P010BE: + case AV_PIX_FMT_P210BE: + case AV_PIX_FMT_P410BE: c->lumToYV12 = p010BEToY_c; break; case AV_PIX_FMT_GRAYF32LE: diff --git a/libswscale/utils.c b/libswscale/utils.c index c726922527..ae92ac9fbc 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -268,6 +268,14 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_Y210LE] = { 1, 0 }, [AV_PIX_FMT_X2RGB10LE] = { 1, 1 }, [AV_PIX_FMT_X2BGR10LE] = { 1, 1 }, + [AV_PIX_FMT_P210BE] = { 1, 0 }, + [AV_PIX_FMT_P210LE] = { 1, 0 }, + [AV_PIX_FMT_P410BE] = { 1, 0 }, + [AV_PIX_FMT_P410LE] = { 1, 0 }, + [AV_PIX_FMT_P216BE] = { 1, 0 }, + [AV_PIX_FMT_P216LE] = { 1, 0 }, + [AV_PIX_FMT_P416BE] = { 1, 0 }, + [AV_PIX_FMT_P416LE] = { 1, 0 }, }; int sws_isSupportedInput(enum AVPixelFormat pix_fmt) diff --git a/libswscale/version.h b/libswscale/version.h index 0d3b7cf363..15ad54319c 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #define LIBSWSCALE_VERSION_MAJOR 6 #define LIBSWSCALE_VERSION_MINOR 1 -#define LIBSWSCALE_VERSION_MICRO 100 +#define LIBSWSCALE_VERSION_MICRO 101 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ From d2229eca5138a9974212f9ef4e7a2eb3d4e04025 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 00:30:28 -0600 Subject: [PATCH 287/894] lavu/videotoolbox: add 422 and 444 pixel format mappings --- configure | 12 ++++++++ libavutil/hwcontext_videotoolbox.c | 44 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/configure b/configure index 4af36bf80a..d7f9429ecd 100755 --- a/configure +++ b/configure @@ -2338,6 +2338,12 @@ TYPES_LIST=" kCMVideoCodecType_HEVC kCMVideoCodecType_HEVCWithAlpha kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange + kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange + kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ kCVImageBufferTransferFunction_ITU_R_2100_HLG kCVImageBufferTransferFunction_Linear @@ -6291,6 +6297,12 @@ enabled videotoolbox && { check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia" check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVCWithAlpha "-framework CoreMedia" check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_ITU_R_2100_HLG "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_Linear "-framework CoreVideo" diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index 25f4e17715..f7a1299cc3 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -53,13 +53,57 @@ static const struct { { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P010 }, { kCVPixelFormatType_420YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P010 }, #endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + { kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV16 }, + { kCVPixelFormatType_422YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV16 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + { kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P210 }, + { kCVPixelFormatType_422YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P210 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE + { kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P216 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + { kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV24 }, + { kCVPixelFormatType_444YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV24 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + { kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P410 }, + { kCVPixelFormatType_444YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P410 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + { kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P416 }, +#endif }; static const enum AVPixelFormat supported_formats[] = { +#ifdef kCFCoreFoundationVersionNumber10_7 AV_PIX_FMT_NV12, +#endif AV_PIX_FMT_YUV420P, AV_PIX_FMT_UYVY422, +#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE AV_PIX_FMT_P010, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV16, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P210, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P216, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV24, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P410, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P416, +#endif AV_PIX_FMT_BGRA, }; From 79e51d6c0f0200c37d8d1f81bd55ea5f405c03fb Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 00:56:33 -0600 Subject: [PATCH 288/894] lavc/videotoolbox: escape 0x00000[0-3]s in avcC PSs --- libavcodec/videotoolbox.c | 53 +++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 49e726a75f..bd6e769207 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -140,14 +140,51 @@ int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) #define AV_W8(p, v) *(p) = (v) +static int escape_ps(uint8_t* dst, const uint8_t* src, int src_size) +{ + int i; + int size = src_size; + uint8_t* p = dst; + + for (i = 0; i < src_size; i++) { + if (i + 2 < src_size && + src[i] == 0x00 && + src[i + 1] == 0x00 && + src[i + 2] <= 0x03) { + if (dst) { + *p++ = src[i++]; + *p++ = src[i++]; + *p++ = 0x03; + } else { + i += 2; + } + size++; + } + if (dst) + *p++ = src[i]; + } + + if (dst) + av_assert0((p - dst) == size); + + return size; +} + CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; H264Context *h = avctx->priv_data; CFDataRef data = NULL; uint8_t *p; - int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size; - uint8_t *vt_extradata = av_malloc(vt_extradata_size); + int sps_size = escape_ps(NULL, h->ps.sps->data, h->ps.sps->data_size); + int pps_size = escape_ps(NULL, h->ps.pps->data, h->ps.pps->data_size); + int vt_extradata_size; + uint8_t *vt_extradata; + int i; + + vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size; + vt_extradata = av_malloc(vt_extradata_size); + if (!vt_extradata) return NULL; @@ -159,14 +196,14 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) AV_W8(p + 3, h->ps.sps->data[3]); /* level */ AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */ AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ - AV_WB16(p + 6, h->ps.sps->data_size); - memcpy(p + 8, h->ps.sps->data, h->ps.sps->data_size); - p += 8 + h->ps.sps->data_size; + AV_WB16(p + 6, sps_size); + p += 8; + p += escape_ps(p, h->ps.sps->data, h->ps.sps->data_size); AV_W8(p + 0, 1); /* number of pps */ - AV_WB16(p + 1, h->ps.pps->data_size); - memcpy(p + 3, h->ps.pps->data, h->ps.pps->data_size); + AV_WB16(p + 1, pps_size); + p += 3; + p += escape_ps(p, h->ps.pps->data, h->ps.pps->data_size); - p += 3 + h->ps.pps->data_size; av_assert0(p - vt_extradata == vt_extradata_size); // save sps header (profile/level) used to create decoder session, From b0c07f293883c5c37b5b1dbfabfca0d695250a60 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 01:00:08 -0600 Subject: [PATCH 289/894] lavc/videotoolbox: fix format computation Use sw_pix_fmt instead of pix_fmt (consistent with other hwaccels) --- libavcodec/videotoolbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index bd6e769207..010f553e57 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1059,7 +1059,7 @@ static int videotoolbox_uninit(AVCodecContext *avctx) } static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { - const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->pix_fmt); + const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->sw_pix_fmt); if (!descriptor) return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context() From f0952f87bcfd905f21ce6cefa8e14a127fb00c8a Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 01:02:26 -0600 Subject: [PATCH 290/894] lavc/videotoolbox: select 4:2:2 and 4:4:4 formats when applicable --- libavcodec/videotoolbox.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 010f553e57..57b37bf3bf 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1064,9 +1064,35 @@ static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context() int depth = descriptor->comp[0].depth; + +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + if (depth > 10) + return descriptor->log2_chroma_w == 0 ? AV_PIX_FMT_P416 : AV_PIX_FMT_P216; +#endif + +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + if (descriptor->log2_chroma_w == 0) { +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + if (depth <= 8) + return AV_PIX_FMT_NV24; +#endif + return AV_PIX_FMT_P410; + } +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + if (descriptor->log2_chroma_h == 0) { +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + if (depth <= 8) + return AV_PIX_FMT_NV16; +#endif + return AV_PIX_FMT_P210; + } +#endif +#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE if (depth > 8) { return AV_PIX_FMT_P010; } +#endif return AV_PIX_FMT_NV12; } From caad1146e25fc5c601b949601b0a13d5a2a08c19 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 01:04:21 -0600 Subject: [PATCH 291/894] lavc/h264dec: support all color formats in videotoolbox hwaccel --- libavcodec/h264_slice.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 89ea16a57f..4467882775 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -811,6 +811,10 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) *fmt++ = AV_PIX_FMT_YUV420P9; break; case 10: +#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + if (h->avctx->colorspace != AVCOL_SPC_RGB) + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) { *fmt++ = AV_PIX_FMT_GBRP10; @@ -849,6 +853,10 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #endif #if CONFIG_H264_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; +#endif +#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + if (h->avctx->colorspace != AVCOL_SPC_RGB) + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) @@ -872,9 +880,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #endif #if CONFIG_H264_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; -#endif -#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL - *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif if (h->avctx->codec->pix_fmts) choices = h->avctx->codec->pix_fmts; From 2c89443e84dc957a606e382d5b0ca118e1f68ce6 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 01:06:29 -0600 Subject: [PATCH 292/894] lavc/hevcdec: support all color formats in videotoolbox hwaccel --- libavcodec/hevcdec.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 3e19f4ebed..46d9edf8eb 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -451,16 +451,25 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; +#endif +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif break; case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV422P10LE: #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif break; - case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P10: +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif + case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P12: #if CONFIG_HEVC_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; From 530c4a7ea95102a806db0ba3d6fcd773fe02806b Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 02:31:52 -0600 Subject: [PATCH 293/894] lavc/videotoolbox: expose some functions as lavc-internal --- libavcodec/videotoolbox.c | 146 ++++++++++++++++++-------------------- libavcodec/vt_internal.h | 10 +++ 2 files changed, 78 insertions(+), 78 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 57b37bf3bf..3022cd1cbf 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -61,9 +61,9 @@ static void videotoolbox_buffer_release(void *opaque, uint8_t *data) av_free(data); } -static int videotoolbox_buffer_copy(VTContext *vtctx, - const uint8_t *buffer, - uint32_t size) +int ff_videotoolbox_buffer_copy(VTContext *vtctx, + const uint8_t *buffer, + uint32_t size) { void *tmp; @@ -376,7 +376,7 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, H264Context *h = avctx->priv_data; if (h->is_avc == 1) { - return videotoolbox_buffer_copy(vtctx, buffer, size); + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); } return 0; @@ -440,18 +440,6 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, return videotoolbox_common_decode_slice(avctx, buffer, size); } -int ff_videotoolbox_uninit(AVCodecContext *avctx) -{ - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - if (vtctx) { - av_freep(&vtctx->bitstream); - if (vtctx->frame) - CVPixelBufferRelease(vtctx->frame); - } - - return 0; -} - #if CONFIG_VIDEOTOOLBOX // Return the AVVideotoolboxContext that matters currently. Where it comes from // depends on the API used. @@ -467,6 +455,43 @@ static AVVideotoolboxContext *videotoolbox_get_context(AVCodecContext *avctx) return avctx->hwaccel_context; } +static void videotoolbox_stop(AVCodecContext *avctx) +{ + AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); + if (!videotoolbox) + return; + + if (videotoolbox->cm_fmt_desc) { + CFRelease(videotoolbox->cm_fmt_desc); + videotoolbox->cm_fmt_desc = NULL; + } + + if (videotoolbox->session) { + VTDecompressionSessionInvalidate(videotoolbox->session); + CFRelease(videotoolbox->session); + videotoolbox->session = NULL; + } +} + +int ff_videotoolbox_uninit(AVCodecContext *avctx) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + if (!vtctx) + return 0; + + av_freep(&vtctx->bitstream); + if (vtctx->frame) + CVPixelBufferRelease(vtctx->frame); + + if (vtctx->vt_ctx) + videotoolbox_stop(avctx); + + av_buffer_unref(&vtctx->cached_hw_frames_ctx); + av_freep(&vtctx->vt_ctx); + + return 0; +} + static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; @@ -903,24 +928,6 @@ static int videotoolbox_start(AVCodecContext *avctx) } } -static void videotoolbox_stop(AVCodecContext *avctx) -{ - AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); - if (!videotoolbox) - return; - - if (videotoolbox->cm_fmt_desc) { - CFRelease(videotoolbox->cm_fmt_desc); - videotoolbox->cm_fmt_desc = NULL; - } - - if (videotoolbox->session) { - VTDecompressionSessionInvalidate(videotoolbox->session); - CFRelease(videotoolbox->session); - videotoolbox->session = NULL; - } -} - static const char *videotoolbox_error_string(OSStatus status) { switch (status) { @@ -934,7 +941,7 @@ static const char *videotoolbox_error_string(OSStatus status) return "unknown"; } -static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) +int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) { OSStatus status; AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); @@ -973,7 +980,7 @@ static int videotoolbox_h264_end_frame(AVCodecContext *avctx) H264Context *h = avctx->priv_data; AVFrame *frame = h->cur_pic_ptr->f; VTContext *vtctx = avctx->internal->hwaccel_priv_data; - int ret = videotoolbox_common_end_frame(avctx, frame); + int ret = ff_videotoolbox_common_end_frame(avctx, frame); vtctx->bitstream_size = 0; return ret; } @@ -1012,7 +1019,7 @@ static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) h->output_frame->crop_top = 0; h->output_frame->crop_bottom = 0; - int ret = videotoolbox_common_end_frame(avctx, frame); + int ret = ff_videotoolbox_common_end_frame(avctx, frame); vtctx->bitstream_size = 0; return ret; } @@ -1023,7 +1030,7 @@ static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx, { VTContext *vtctx = avctx->internal->hwaccel_priv_data; - return videotoolbox_buffer_copy(vtctx, buffer, size); + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); } static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx, @@ -1038,24 +1045,7 @@ static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx) MpegEncContext *s = avctx->priv_data; AVFrame *frame = s->current_picture_ptr->f; - return videotoolbox_common_end_frame(avctx, frame); -} - -static int videotoolbox_uninit(AVCodecContext *avctx) -{ - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - if (!vtctx) - return 0; - - ff_videotoolbox_uninit(avctx); - - if (vtctx->vt_ctx) - videotoolbox_stop(avctx); - - av_buffer_unref(&vtctx->cached_hw_frames_ctx); - av_freep(&vtctx->vt_ctx); - - return 0; + return ff_videotoolbox_common_end_frame(avctx, frame); } static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { @@ -1097,7 +1087,7 @@ static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) return AV_PIX_FMT_NV12; } -static int videotoolbox_common_init(AVCodecContext *avctx) +int ff_videotoolbox_common_init(AVCodecContext *avctx) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; AVHWFramesContext *hw_frames; @@ -1169,12 +1159,12 @@ static int videotoolbox_common_init(AVCodecContext *avctx) return 0; fail: - videotoolbox_uninit(avctx); + ff_videotoolbox_uninit(avctx); return err; } -static int videotoolbox_frame_params(AVCodecContext *avctx, - AVBufferRef *hw_frames_ctx) +int ff_videotoolbox_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; @@ -1195,9 +1185,9 @@ const AVHWAccel ff_h263_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1211,9 +1201,9 @@ const AVHWAccel ff_hevc_videotoolbox_hwaccel = { .decode_slice = videotoolbox_hevc_decode_slice, .decode_params = videotoolbox_hevc_decode_params, .end_frame = videotoolbox_hevc_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1227,9 +1217,9 @@ const AVHWAccel ff_h264_videotoolbox_hwaccel = { .decode_slice = ff_videotoolbox_h264_decode_slice, .decode_params = videotoolbox_h264_decode_params, .end_frame = videotoolbox_h264_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1242,9 +1232,9 @@ const AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1257,9 +1247,9 @@ const AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1272,9 +1262,9 @@ const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h index fb64735b8c..e2f279d0fc 100644 --- a/libavcodec/vt_internal.h +++ b/libavcodec/vt_internal.h @@ -19,6 +19,9 @@ #ifndef AVCODEC_VT_INTERNAL_H #define AVCODEC_VT_INTERNAL_H +#include "avcodec.h" +#include "videotoolbox.h" + typedef struct VTContext { // The current bitstream buffer. uint8_t *bitstream; @@ -45,6 +48,12 @@ typedef struct VTContext { } VTContext; int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame); +int ff_videotoolbox_common_init(AVCodecContext *avctx); +int ff_videotoolbox_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx); +int ff_videotoolbox_buffer_copy(VTContext *vtctx, + const uint8_t *buffer, + uint32_t size); int ff_videotoolbox_uninit(AVCodecContext *avctx); int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, const uint8_t *buffer, @@ -52,6 +61,7 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size); +int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame); CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx); From e3c6cc96cf2f0b2c22dee80a53a01a5fe4fea009 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 02:33:08 -0600 Subject: [PATCH 294/894] lavc/videotoolbox: call VTRegisterSupplementalVideoDecoderIfAvailable This is required for VP9 to work. --- libavcodec/videotoolbox.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 3022cd1cbf..a11d494915 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -32,6 +32,7 @@ #include "h264dec.h" #include "hevcdec.h" #include "mpegvideo.h" +#include #include #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder @@ -866,6 +867,12 @@ static int videotoolbox_start(AVCodecContext *avctx) break; } +#ifdef __MAC_10_11 + if (__builtin_available(macOS 10.11, *)) { + VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type); + } +#endif + decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx); if (!decoder_spec) { From a41a2efc85f8c88caec10040ee437562f9d0b947 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 02:43:06 -0600 Subject: [PATCH 295/894] lavc/videotoolbox: add VP9 hardware acceleration On M1 Max, this supports profiles 0 and 2, but not 1 and 3. --- Changelog | 1 + configure | 4 + libavcodec/Makefile | 1 + libavcodec/hwaccels.h | 1 + libavcodec/videotoolbox.c | 17 ++++- libavcodec/videotoolbox_vp9.c | 140 ++++++++++++++++++++++++++++++++++ libavcodec/vp9.c | 9 ++- libavcodec/vt_internal.h | 1 + 8 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 libavcodec/videotoolbox_vp9.c diff --git a/Changelog b/Changelog index a66231b4d8..a520b832b2 100644 --- a/Changelog +++ b/Changelog @@ -33,6 +33,7 @@ version : - colorspectrum source video filter - RTP packetizer for uncompressed video (RFC 4175) - bitpacked encoder +- VideoToolbox VP9 hwaccel version 4.4: diff --git a/configure b/configure index d7f9429ecd..07b168af72 100755 --- a/configure +++ b/configure @@ -2337,6 +2337,7 @@ TOOLCHAIN_FEATURES=" TYPES_LIST=" kCMVideoCodecType_HEVC kCMVideoCodecType_HEVCWithAlpha + kCMVideoCodecType_VP9 kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange @@ -3092,6 +3093,8 @@ vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" vp9_vaapi_hwaccel_select="vp9_decoder" vp9_vdpau_hwaccel_deps="vdpau VdpPictureInfoVP9" vp9_vdpau_hwaccel_select="vp9_decoder" +vp9_videotoolbox_hwaccel_deps="videotoolbox" +vp9_videotoolbox_hwaccel_select="vp9_decoder" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" @@ -6296,6 +6299,7 @@ enabled videotoolbox && { check_lib coreservices CoreServices/CoreServices.h UTGetOSTypeFromString "-framework CoreServices" check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia" check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVCWithAlpha "-framework CoreMedia" + check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_VP9 "-framework CoreMedia" check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo" check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange "-framework CoreVideo" check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange "-framework CoreVideo" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6be90cd5c0..4122a9b144 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -976,6 +976,7 @@ OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o +OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o # libavformat dependencies diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 8e54cf73f9..65e778f3e4 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -74,6 +74,7 @@ extern const AVHWAccel ff_vp9_dxva2_hwaccel; extern const AVHWAccel ff_vp9_nvdec_hwaccel; extern const AVHWAccel ff_vp9_vaapi_hwaccel; extern const AVHWAccel ff_vp9_vdpau_hwaccel; +extern const AVHWAccel ff_vp9_videotoolbox_hwaccel; extern const AVHWAccel ff_wmv3_d3d11va_hwaccel; extern const AVHWAccel ff_wmv3_d3d11va2_hwaccel; extern const AVHWAccel ff_wmv3_dxva2_hwaccel; diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index a11d494915..5f08488a6b 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -33,6 +33,7 @@ #include "hevcdec.h" #include "mpegvideo.h" #include +#include #include #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder @@ -46,6 +47,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; #endif +#if !HAVE_KCMVIDEOCODECTYPE_VP9 +enum { kCMVideoCodecType_VP9 = 'vp09' }; +#endif + #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 typedef struct VTHWFrame { @@ -816,6 +821,11 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec if (data) CFDictionarySetValue(avc_info, CFSTR("hvcC"), data); break; + case kCMVideoCodecType_VP9 : + data = ff_videotoolbox_vpcc_extradata_create(avctx); + if (data) + CFDictionarySetValue(avc_info, CFSTR("vpcC"), data); + break; default: break; } @@ -863,12 +873,15 @@ static int videotoolbox_start(AVCodecContext *avctx) case AV_CODEC_ID_MPEG4 : videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video; break; + case AV_CODEC_ID_VP9 : + videotoolbox->cm_codec_type = kCMVideoCodecType_VP9; + break; default : break; } -#ifdef __MAC_10_11 - if (__builtin_available(macOS 10.11, *)) { +#if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) + if (__builtin_available(macOS 11.0, *)) { VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type); } #endif diff --git a/libavcodec/videotoolbox_vp9.c b/libavcodec/videotoolbox_vp9.c new file mode 100644 index 0000000000..1b6d08f00b --- /dev/null +++ b/libavcodec/videotoolbox_vp9.c @@ -0,0 +1,140 @@ +/* + * Videotoolbox hardware acceleration for VP9 + * + * copyright (c) 2021 rcombs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "videotoolbox.h" +#include "libavutil/hwcontext_videotoolbox.h" +#include "vt_internal.h" +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" +#include "decode.h" +#include "internal.h" +#include "vp9shared.h" + +enum VPX_CHROMA_SUBSAMPLING +{ + VPX_SUBSAMPLING_420_VERTICAL = 0, + VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1, + VPX_SUBSAMPLING_422 = 2, + VPX_SUBSAMPLING_444 = 3, +}; + +static int get_vpx_chroma_subsampling(enum AVPixelFormat pixel_format, + enum AVChromaLocation chroma_location) +{ + int chroma_w, chroma_h; + if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) { + if (chroma_w == 1 && chroma_h == 1) { + return (chroma_location == AVCHROMA_LOC_LEFT) + ? VPX_SUBSAMPLING_420_VERTICAL + : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA; + } else if (chroma_w == 1 && chroma_h == 0) { + return VPX_SUBSAMPLING_422; + } else if (chroma_w == 0 && chroma_h == 0) { + return VPX_SUBSAMPLING_444; + } + } + return -1; +} + +CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx) +{ + const VP9SharedContext *h = avctx->priv_data; + CFDataRef data = NULL; + uint8_t *p; + int vt_extradata_size; + uint8_t *vt_extradata; + int subsampling = get_vpx_chroma_subsampling(avctx->sw_pix_fmt, avctx->chroma_sample_location); + + vt_extradata_size = 1 + 3 + 6 + 2; + vt_extradata = av_malloc(vt_extradata_size); + + if (subsampling < 0) + return NULL; + + if (!vt_extradata) + return NULL; + + p = vt_extradata; + + *p++ = 1; /* version */ + AV_WB24(p + 1, 0); /* flags */ + p += 3; + + *p++ = h->h.profile; + *p++ = avctx->level; + *p++ = (h->h.bpp << 4) | (subsampling << 1) | (avctx->color_range == AVCOL_RANGE_JPEG); + *p++ = avctx->color_primaries; + *p++ = avctx->color_trc; + *p++ = avctx->colorspace; + + AV_WB16(p + 0, 0); + p += 2; + + av_assert0(p - vt_extradata == vt_extradata_size); + + data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); + av_free(vt_extradata); + return data; +} + +static int videotoolbox_vp9_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + return 0; +} + +static int videotoolbox_vp9_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); +} + +static int videotoolbox_vp9_end_frame(AVCodecContext *avctx) +{ + const VP9SharedContext *h = avctx->priv_data; + AVFrame *frame = h->frames[CUR_FRAME].tf.f; + + return ff_videotoolbox_common_end_frame(avctx, frame); +} + +const AVHWAccel ff_vp9_videotoolbox_hwaccel = { + .name = "vp9_videotoolbox", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, + .alloc_frame = ff_videotoolbox_alloc_frame, + .start_frame = videotoolbox_vp9_start_frame, + .decode_slice = videotoolbox_vp9_decode_slice, + .end_frame = videotoolbox_vp9_end_frame, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), +}; diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 8317ac6bd8..24841c5b9f 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -181,7 +181,8 @@ static int update_size(AVCodecContext *avctx, int w, int h) CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ CONFIG_VP9_NVDEC_HWACCEL + \ CONFIG_VP9_VAAPI_HWACCEL + \ - CONFIG_VP9_VDPAU_HWACCEL) + CONFIG_VP9_VDPAU_HWACCEL + \ + CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; VP9Context *s = avctx->priv_data; uint8_t *p; @@ -212,6 +213,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) #endif #if CONFIG_VP9_VDPAU_HWACCEL *fmtp++ = AV_PIX_FMT_VDPAU; +#endif +#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + *fmtp++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif break; case AV_PIX_FMT_YUV420P12: @@ -1893,6 +1897,9 @@ const AVCodec ff_vp9_decoder = { #endif #if CONFIG_VP9_VDPAU_HWACCEL HWACCEL_VDPAU(vp9), +#endif +#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(vp9), #endif NULL }, diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h index e2f279d0fc..54a11fd1b5 100644 --- a/libavcodec/vt_internal.h +++ b/libavcodec/vt_internal.h @@ -64,5 +64,6 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame); CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx); +CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx); #endif /* AVCODEC_VT_INTERNAL_H */ From 350eb59f8c25372067b7e338b45cce97fe892e4f Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 14:21:23 -0600 Subject: [PATCH 296/894] videotoolbox: add alpha support --- libavcodec/videotoolbox.c | 3 +++ libavutil/hwcontext_videotoolbox.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 5f08488a6b..542fe9316a 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1075,6 +1075,9 @@ static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) int depth = descriptor->comp[0].depth; + if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) + return AV_PIX_FMT_AYUV64; + #if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE if (depth > 10) return descriptor->log2_chroma_w == 0 ? AV_PIX_FMT_P416 : AV_PIX_FMT_P216; diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index f7a1299cc3..e9567bbf44 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -48,6 +48,7 @@ static const struct { #ifdef kCFCoreFoundationVersionNumber10_7 { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV12 }, { kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV12 }, + { kCVPixelFormatType_4444AYpCbCr16, false, AV_PIX_FMT_AYUV64 }, #endif #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P010 }, @@ -80,6 +81,7 @@ static const struct { static const enum AVPixelFormat supported_formats[] = { #ifdef kCFCoreFoundationVersionNumber10_7 AV_PIX_FMT_NV12, + AV_PIX_FMT_AYUV64, #endif AV_PIX_FMT_YUV420P, AV_PIX_FMT_UYVY422, From 805bf2ebc94b6a0583fa6ea8cfd4a797c8f20850 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 13:37:26 -0600 Subject: [PATCH 297/894] lavc/proresdec: add scaffolding for hwdec support --- libavcodec/proresdec.h | 1 + libavcodec/proresdec2.c | 48 ++++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/libavcodec/proresdec.h b/libavcodec/proresdec.h index 06e41dd09a..1e48752e6f 100644 --- a/libavcodec/proresdec.h +++ b/libavcodec/proresdec.h @@ -52,6 +52,7 @@ typedef struct { int first_field; int alpha_info; void (*unpack_alpha)(GetBitContext *gb, uint16_t *dst, int num_coeffs, const int num_bits); + enum AVPixelFormat pix_fmt; } ProresContext; #endif /* AVCODEC_PRORESDEC_H */ diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 7750620b22..5b1d7da693 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -187,6 +187,8 @@ static av_cold int decode_init(AVCodecContext *avctx) permute(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation); permute(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation); + ctx->pix_fmt = AV_PIX_FMT_NONE; + if (avctx->bits_per_raw_sample == 10){ ctx->unpack_alpha = unpack_alpha_10; } else if (avctx->bits_per_raw_sample == 12){ @@ -204,6 +206,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, int hdr_size, width, height, flags; int version; const uint8_t *ptr; + enum AVPixelFormat pix_fmt; hdr_size = AV_RB16(buf); ff_dlog(avctx, "header size %d\n", hdr_size); @@ -252,18 +255,34 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, if (ctx->alpha_info) { if (avctx->bits_per_raw_sample == 10) { - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; } else { /* 12b */ - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12; } } else { if (avctx->bits_per_raw_sample == 10) { - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; } else { /* 12b */ - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12; } } + if (pix_fmt != ctx->pix_fmt) { +#define HWACCEL_MAX 0 + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; + int ret; + + ctx->pix_fmt = pix_fmt; + + *fmtp++ = ctx->pix_fmt; + *fmtp = AV_PIX_FMT_NONE; + + if ((ret = ff_thread_get_format(avctx, pix_fmts)) < 0) + return ret; + + avctx->pix_fmt = ret; + } + avctx->color_primaries = buf[14]; avctx->color_trc = buf[15]; avctx->colorspace = buf[16]; @@ -782,6 +801,22 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, buf += frame_hdr_size; buf_size -= frame_hdr_size; + if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + return ret; + + if (avctx->hwaccel) { + ret = avctx->hwaccel->start_frame(avctx, NULL, 0); + if (ret < 0) + return ret; + ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size); + if (ret < 0) + return ret; + ret = avctx->hwaccel->end_frame(avctx); + if (ret < 0) + return ret; + goto finish; + } + decode_picture: pic_size = decode_picture_header(avctx, buf, buf_size); if (pic_size < 0) { @@ -789,10 +824,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return pic_size; } - if (ctx->first_field) - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) - return ret; - if ((ret = decode_picture(avctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding picture\n"); return ret; @@ -806,6 +837,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto decode_picture; } +finish: *got_frame = 1; return avpkt->size; From da0179b262a5e30e3c35fa2f522356ade68dc08e Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 13:38:04 -0600 Subject: [PATCH 298/894] lavc/proresdec: add videotoolbox hwaccel --- Changelog | 1 + configure | 2 ++ libavcodec/hwaccels.h | 1 + libavcodec/proresdec2.c | 12 ++++++- libavcodec/videotoolbox.c | 74 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index a520b832b2..56faa7f9f5 100644 --- a/Changelog +++ b/Changelog @@ -34,6 +34,7 @@ version : - RTP packetizer for uncompressed video (RFC 4175) - bitpacked encoder - VideoToolbox VP9 hwaccel +- VideoToolbox ProRes hwaccel version 4.4: diff --git a/configure b/configure index 07b168af72..d8b5be8bbb 100755 --- a/configure +++ b/configure @@ -3065,6 +3065,8 @@ mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" mpeg4_videotoolbox_hwaccel_deps="videotoolbox" mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder" +prores_videotoolbox_hwaccel_deps="videotoolbox" +prores_videotoolbox_hwaccel_select="prores_decoder" vc1_d3d11va_hwaccel_deps="d3d11va" vc1_d3d11va_hwaccel_select="vc1_decoder" vc1_d3d11va2_hwaccel_deps="d3d11va" diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 65e778f3e4..1e7b464950 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -60,6 +60,7 @@ extern const AVHWAccel ff_mpeg4_nvdec_hwaccel; extern const AVHWAccel ff_mpeg4_vaapi_hwaccel; extern const AVHWAccel ff_mpeg4_vdpau_hwaccel; extern const AVHWAccel ff_mpeg4_videotoolbox_hwaccel; +extern const AVHWAccel ff_prores_videotoolbox_hwaccel; extern const AVHWAccel ff_vc1_d3d11va_hwaccel; extern const AVHWAccel ff_vc1_d3d11va2_hwaccel; extern const AVHWAccel ff_vc1_dxva2_hwaccel; diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 5b1d7da693..719194f21e 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "get_bits.h" +#include "hwconfig.h" #include "idctdsp.h" #include "internal.h" #include "profiles.h" @@ -268,12 +269,15 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, } if (pix_fmt != ctx->pix_fmt) { -#define HWACCEL_MAX 0 +#define HWACCEL_MAX (CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; int ret; ctx->pix_fmt = pix_fmt; +#if CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL + *fmtp++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif *fmtp++ = ctx->pix_fmt; *fmtp = AV_PIX_FMT_NONE; @@ -864,4 +868,10 @@ const AVCodec ff_prores_decoder = { .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .hw_configs = (const AVCodecHWConfigInternal *const []) { +#if CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(prores), +#endif + NULL + }, }; diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 542fe9316a..40d231acc1 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -32,6 +32,7 @@ #include "h264dec.h" #include "hevcdec.h" #include "mpegvideo.h" +#include "proresdec.h" #include #include #include @@ -186,7 +187,6 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) int pps_size = escape_ps(NULL, h->ps.pps->data, h->ps.pps->data_size); int vt_extradata_size; uint8_t *vt_extradata; - int i; vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size; vt_extradata = av_malloc(vt_extradata_size); @@ -873,6 +873,31 @@ static int videotoolbox_start(AVCodecContext *avctx) case AV_CODEC_ID_MPEG4 : videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video; break; + case AV_CODEC_ID_PRORES : + switch (avctx->codec_tag) { + case MKTAG('a','p','c','o'): + videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422Proxy; + break; + case MKTAG('a','p','c','s'): + videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422LT; + break; + case MKTAG('a','p','c','n'): + videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422; + break; + case MKTAG('a','p','c','h'): + videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422HQ; + break; + case MKTAG('a','p','4','h'): + videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes4444; + break; + case MKTAG('a','p','4','x'): + videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes4444XQ; + break; + default: + videotoolbox->cm_codec_type = avctx->codec_tag; + av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag); + } + break; case AV_CODEC_ID_VP9 : videotoolbox->cm_codec_type = kCMVideoCodecType_VP9; break; @@ -880,6 +905,14 @@ static int videotoolbox_start(AVCodecContext *avctx) break; } +#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) + if (avctx->codec_id == AV_CODEC_ID_PRORES) { + if (__builtin_available(macOS 10.9, *)) { + VTRegisterProfessionalVideoWorkflowVideoDecoders(); + } + } +#endif + #if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) if (__builtin_available(macOS 11.0, *)) { VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type); @@ -1068,6 +1101,30 @@ static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx) return ff_videotoolbox_common_end_frame(avctx, frame); } +static int videotoolbox_prores_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + return 0; +} + +static int videotoolbox_prores_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); +} + +static int videotoolbox_prores_end_frame(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + AVFrame *frame = ctx->frame; + + return ff_videotoolbox_common_end_frame(avctx, frame); +} + static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->sw_pix_fmt); if (!descriptor) @@ -1291,6 +1348,21 @@ const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; +const AVHWAccel ff_prores_videotoolbox_hwaccel = { + .name = "prores_videotoolbox", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, + .alloc_frame = ff_videotoolbox_alloc_frame, + .start_frame = videotoolbox_prores_start_frame, + .decode_slice = videotoolbox_prores_decode_slice, + .end_frame = videotoolbox_prores_end_frame, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), +}; + static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, bool full_range) { From 4cedf44aae273df937daf81b7b798539e880b20f Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 13 Nov 2021 17:46:31 -0600 Subject: [PATCH 299/894] lavc: bump minor version for new VT hwaccels --- libavcodec/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 58e3322e9a..8a0b94f5aa 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 14 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From c7e527f7f395f23d6b41e54c21cd50b110f83f82 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sun, 28 Nov 2021 17:15:34 -0600 Subject: [PATCH 300/894] lavc/videotoolbox: fix build on pre-10.14 SDKs Also fixes handling of future codec tags (needed to bswap) --- libavcodec/videotoolbox.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 40d231acc1..d2907aee56 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -875,27 +875,15 @@ static int videotoolbox_start(AVCodecContext *avctx) break; case AV_CODEC_ID_PRORES : switch (avctx->codec_tag) { - case MKTAG('a','p','c','o'): - videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422Proxy; - break; - case MKTAG('a','p','c','s'): - videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422LT; - break; - case MKTAG('a','p','c','n'): - videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422; - break; - case MKTAG('a','p','c','h'): - videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes422HQ; - break; - case MKTAG('a','p','4','h'): - videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes4444; - break; - case MKTAG('a','p','4','x'): - videotoolbox->cm_codec_type = kCMVideoCodecType_AppleProRes4444XQ; - break; default: - videotoolbox->cm_codec_type = avctx->codec_tag; av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag); + case MKTAG('a','p','c','o'): // kCMVideoCodecType_AppleProRes422Proxy + case MKTAG('a','p','c','s'): // kCMVideoCodecType_AppleProRes422LT + case MKTAG('a','p','c','n'): // kCMVideoCodecType_AppleProRes422 + case MKTAG('a','p','c','h'): // kCMVideoCodecType_AppleProRes422HQ + case MKTAG('a','p','4','h'): // kCMVideoCodecType_AppleProRes4444 + case MKTAG('a','p','4','x'): // kCMVideoCodecType_AppleProRes4444XQ + videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag); } break; case AV_CODEC_ID_VP9 : From 0d924d6e5a4272149bd5ea87d63cbb6e67732345 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 28 Nov 2021 20:23:26 -0300 Subject: [PATCH 301/894] avcodec/videotoolbox: silence some -Wimplicit-fallthrough warnings Signed-off-by: James Almer --- libavcodec/videotoolbox.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index d2907aee56..284da97541 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -877,6 +877,7 @@ static int videotoolbox_start(AVCodecContext *avctx) switch (avctx->codec_tag) { default: av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag); + // fall-through case MKTAG('a','p','c','o'): // kCMVideoCodecType_AppleProRes422Proxy case MKTAG('a','p','c','s'): // kCMVideoCodecType_AppleProRes422LT case MKTAG('a','p','c','n'): // kCMVideoCodecType_AppleProRes422 @@ -884,6 +885,7 @@ static int videotoolbox_start(AVCodecContext *avctx) case MKTAG('a','p','4','h'): // kCMVideoCodecType_AppleProRes4444 case MKTAG('a','p','4','x'): // kCMVideoCodecType_AppleProRes4444XQ videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag); + break; } break; case AV_CODEC_ID_VP9 : From 86a2123a6ea69f3f6d1e30c7cb35478ab3620a0d Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 26 Nov 2021 20:47:20 +0800 Subject: [PATCH 302/894] avfilter/src_movie: add format_opts for the opened file Signed-off-by: Limin Wang --- doc/filters.texi | 9 +++++++++ libavfilter/src_movie.c | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 3731a14521..a1b212d38a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -28395,6 +28395,15 @@ timestamps. @item dec_threads Specifies the number of threads for decoding + +@item format_opts +Specify format options for the opened file. Format options can be specified +as a list of @var{key}=@var{value} pairs separated by ':'. The following example +shows how to add protocol_whitelist and protocol_blacklist options: +@example +ffplay -f lavfi +"movie=filename='1.sdp':format_opts='protocol_whitelist=file,rtp,udp\:protocol_blacklist=http'" +@end example @end table It allows overlaying a second video on top of the main input of diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 220a43cdd1..b89a680883 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -74,6 +74,7 @@ typedef struct MovieContext { int max_stream_index; /**< max stream # actually used for output */ MovieStream *st; /**< array of all streams, one per output */ int *out_index; /**< stream number -> output number map, or -1 */ + AVDictionary *format_opts; } MovieContext; #define OFFSET(x) offsetof(MovieContext, x) @@ -92,6 +93,7 @@ static const AVOption movie_options[]= { { "loop", "set loop count", OFFSET(loop_count), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, FLAGS }, { "discontinuity", "set discontinuity threshold", OFFSET(discontinuity_threshold), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS }, { "dec_threads", "set the number of threads for decoding", OFFSET(dec_threads), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, + { "format_opts", "set format options for the opened file", OFFSET(format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, { NULL }, }; @@ -243,7 +245,7 @@ static av_cold int movie_common_init(AVFilterContext *ctx) iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL; movie->format_ctx = NULL; - if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) { + if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, &movie->format_opts)) < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to avformat_open_input '%s'\n", movie->file_name); return ret; From 2877ddddda04d5c04beaf4482acfa3151c343313 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 13 Nov 2021 18:57:59 +0100 Subject: [PATCH 303/894] avcodec/vqavideo: Use GetByteContext and check for end Fixes: out of array access Fixes: Timeout Fixes: 40481/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VQA_fuzzer-6502647583080448 Signed-off-by: Michael Niedermayer --- libavcodec/vqavideo.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 61f0a2c950..7c1d42bcac 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -633,7 +633,7 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) int vptr_chunk = -1; int vprz_chunk = -1; - const unsigned char *stream; + GetByteContext gb_stream; while (bytestream2_get_bytes_left(&s->gb) >= 8) { chunk_type = bytestream2_get_be32u(&s->gb); @@ -717,7 +717,7 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */ - stream = (unsigned char*)s->decode_buffer; + bytestream2_init(&gb_stream, s->decode_buffer, s->decode_buffer_size); for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) { int x_pos = 0; @@ -725,9 +725,14 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) while (x_pos < s->width) { int vector_index = 0; int count = 0; - uint16_t code = bytestream_get_le16(&stream); + uint16_t code; int type; + if (bytestream2_get_bytes_left(&gb_stream) < 2) + return AVERROR_INVALIDDATA; + + code = bytestream2_get_le16(&gb_stream); + type = code >> 13; code &= 0x1fff; @@ -742,7 +747,7 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) count = 1; } else if (type < 7) { vector_index = code; - count = *stream++; + count = bytestream2_get_byte(&gb_stream); } else { av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type); return AVERROR_INVALIDDATA; @@ -771,7 +776,7 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) /* we might want to read the next block index from stream */ if ((type == 2) && count > 0) { - vector_index = bytestream_get_byte(&stream); + vector_index = bytestream2_get_byte(&gb_stream); } x_pos += 4; From 3a64a4c58255d45e05eff80c9464ad3bdc2d6463 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 7 Nov 2021 13:48:24 +0100 Subject: [PATCH 304/894] avformat/mov: Check channels for mov_parse_stsd_audio() Fixes: signed integer overflow: -776522110086937600 * 16 cannot be represented in type 'long' Fixes: 40563/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-6644829447127040 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 451cb78bbf..5c74d099da 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2538,6 +2538,10 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate); return AVERROR_INVALIDDATA; } + if (st->codecpar->channels < 0) { + av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->channels); + return AVERROR_INVALIDDATA; + } } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){ mov_parse_stsd_subtitle(c, pb, st, sc, size - (avio_tell(pb) - start_pos)); From 76c41a5bfeceb6d4a5c656abe41791f08c3b011c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 2 Oct 2021 23:08:14 +0200 Subject: [PATCH 305/894] tools/target_dec_fuzzer: Disable MB debug after a few iterations This debug code can be quite slow on constructed streams Fixes: Timeout Fixes: 38907/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_H264_fuzzer-6334628852531200 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 1a790f6642..15466a76d5 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -392,8 +392,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { decode_more = ret >= 0; if(!decode_more) { ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); - if (it > 20 || ec_pixels > 4 * ctx->max_pixels) + if (it > 20 || ec_pixels > 4 * ctx->max_pixels) { ctx->error_concealment = 0; + ctx->debug &= ~(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE); + } if (ec_pixels > maxpixels) goto maximums_reached; } @@ -406,8 +408,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int ret = decode_handler(ctx, frame, &got_frame, avpkt); ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); - if (it > 20 || ec_pixels > 4 * ctx->max_pixels) + if (it > 20 || ec_pixels > 4 * ctx->max_pixels) { ctx->error_concealment = 0; + ctx->debug &= ~(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE); + } if (ec_pixels > maxpixels) goto maximums_reached; From 3809467d4dc26a1ec7d7afb617c2a1f89eaa6a8b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 2 Oct 2021 23:37:05 +0200 Subject: [PATCH 306/894] avcodec/iff: limit written bytes to twice the output array size in decode_delta_l() Fixes: Timeout Fixes: 39436/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_IFF_ILBM_fuzzer-6624915520880640 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/iff.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/iff.c b/libavcodec/iff.c index 6a4c466b44..1dcf0e00ed 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -1456,6 +1456,7 @@ static void decode_delta_l(uint8_t *dst, int planepitch_byte = (w + 7) / 8; int planepitch = ((w + 15) / 16) * 2; int pitch = planepitch * bpp; + int count = 0; if (buf_end - buf <= 64) return; @@ -1487,6 +1488,8 @@ static void decode_delta_l(uint8_t *dst, int16_t cnt = bytestream2_get_be16(&ogb); uint16_t data; + if (count > dst_size) + break; offset = ((2 * offset) / planepitch_byte) * pitch + ((2 * offset) % planepitch_byte) + k * planepitch; if (cnt < 0) { if (bytestream2_get_bytes_left(&dgb) < 2) @@ -1494,6 +1497,7 @@ static void decode_delta_l(uint8_t *dst, bytestream2_seek_p(&pb, offset, SEEK_SET); cnt = -cnt; data = bytestream2_get_be16(&dgb); + count += cnt; for (i = 0; i < cnt; i++) { bytestream2_put_be16(&pb, data); bytestream2_skip_p(&pb, dstpitch - 2); @@ -1502,6 +1506,7 @@ static void decode_delta_l(uint8_t *dst, if (bytestream2_get_bytes_left(&dgb) < 2*cnt) break; bytestream2_seek_p(&pb, offset, SEEK_SET); + count += cnt; for (i = 0; i < cnt; i++) { data = bytestream2_get_be16(&dgb); bytestream2_put_be16(&pb, data); From 1c2dae153cd6574252fbcf60fb3782440ef43056 Mon Sep 17 00:00:00 2001 From: asilvestre Date: Fri, 26 Nov 2021 17:27:18 +0100 Subject: [PATCH 307/894] avformat/flvenc: avoid 24bit timestamp truncation for FLV metadata FLV AMF tags have a 24bit field for timestamps plus an 8bit for extended timestamps. All FLV AMF tags except when we write metadata handle this correctly using the put_timestamp function. Until now when writing metadata we were only using the first 24 bits and thus the timestamp value was wraping around 4 hours 40 minutes (16,800,000 ms, max 24 bit value 16,777,216) of playback. This commit fixes this applying this same function put_timestamp for the metadata FLV tag. Signed-off-by: Marton Balint --- libavformat/flvenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index c5926575a1..5130d429ad 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -284,8 +284,8 @@ static void write_metadata(AVFormatContext *s, unsigned int ts) avio_w8(pb, FLV_TAG_TYPE_META); // tag type META flv->metadata_size_pos = avio_tell(pb); avio_wb24(pb, 0); // size of data part (sum of all parts below) - avio_wb24(pb, ts); // timestamp - avio_wb32(pb, 0); // reserved + put_timestamp(pb, ts); // timestamp + avio_wb24(pb, 0); // reserved /* now data of data_size size */ From 939711905a3674684a13635828e6784ebb7d1cde Mon Sep 17 00:00:00 2001 From: softworkz Date: Thu, 25 Nov 2021 04:01:23 +0100 Subject: [PATCH 308/894] fftools/ffprobe: print size of attachment streams (extradata_size) Signed-off-by: softworkz Signed-off-by: Marton Balint --- doc/ffprobe.xsd | 1 + fftools/ffprobe.c | 1 + tests/ref/fate/concat-demuxer-extended-lavf-mxf | 2 +- tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 | 2 +- tests/ref/fate/concat-demuxer-simple1-lavf-mxf | 2 +- tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 | 2 +- tests/ref/fate/concat-demuxer-simple2-lavf-ts | 2 +- tests/ref/fate/flv-demux | 4 ++-- tests/ref/fate/mov-zombie | 2 +- tests/ref/fate/mxf-probe-d10 | 1 + tests/ref/fate/oggopus-demux | 2 +- tests/ref/fate/ts-demux | 2 +- tests/ref/fate/ts-opus-demux | 2 +- tests/ref/fate/ts-small-demux | 2 +- 14 files changed, 15 insertions(+), 12 deletions(-) diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd index b65e54dbef..3af621a17a 100644 --- a/doc/ffprobe.xsd +++ b/doc/ffprobe.xsd @@ -215,6 +215,7 @@ + diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 169c26b65c..0711e02922 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2769,6 +2769,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id par->extradata_size); if (par->extradata_size > 0) { + print_int("extradata_size", par->extradata_size); writer_print_data_hash(w, "extradata_hash", par->extradata, par->extradata_size); } diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf b/tests/ref/fate/concat-demuxer-extended-lavf-mxf index a3b205539a..4b2a8624db 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf @@ -1 +1 @@ -0ea04f40869068b282a67e5b8f2a6127 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe +29e4e502a912b6d863e75d44e156ed31 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 index 9cbc8df831..1dedc6bf43 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 @@ -1 +1 @@ -88abe27eddff160aafd622ed02c26eb6 *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe +8de04a786521677a593283c44a53572e *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf index fc8034bd29..2fe703e2a6 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf @@ -120,5 +120,5 @@ audio|1|65280|1.360000|65280|1.360000|1920|0.040000|3840|207872|K_|1 Strings Metadata video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1 Strings Metadata -0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 +0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|1|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|768000|N/A|N/A|N/A|N/A|50|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 index 59c6372ef2..0a3af658f6 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 @@ -78,5 +78,5 @@ video|0|34|1.360000|34|1.360000|1|0.040000|150000|1924096|K_|1 Strings Metadata audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1 Strings Metadata -0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 +0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|2|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|1536000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple2-lavf-ts b/tests/ref/fate/concat-demuxer-simple2-lavf-ts index b9106f0ea9..76dde3b873 100644 --- a/tests/ref/fate/concat-demuxer-simple2-lavf-ts +++ b/tests/ref/fate/concat-demuxer-simple2-lavf-ts @@ -212,4 +212,4 @@ video|1|171982|1.910911|168382|1.870911|3600|0.040000|17440|206988|__MPEGTS Stre video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 0|mp2|unknown|audio|[3][0][0][0]|0x0003|s16p|44100|1|mono|0|N/A|0/0|0/0|1/90000|0|0.000000|N/A|N/A|64000|N/A|N/A|N/A|N/A|89|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 0 -1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1 +1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1 diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux index 9daee0594e..fffc1c38c4 100644 --- a/tests/ref/fate/flv-demux +++ b/tests/ref/fate/flv-demux @@ -603,6 +603,6 @@ packet|codec_type=video|stream_index=0|pts=11612|pts_time=11.612000|dts=11612|dt packet|codec_type=video|stream_index=0|pts=11645|pts_time=11.645000|dts=11645|dts_time=11.645000|duration=33|duration_time=0.033000|size=2600|pos=507811|flags=__|data_hash=CRC32:d35f9e6f packet|codec_type=audio|stream_index=1|pts=11656|pts_time=11.656000|dts=11656|dts_time=11.656000|duration=46|duration_time=0.046000|size=346|pos=510431|flags=K_|data_hash=CRC32:4e6b44cb packet|codec_type=video|stream_index=0|pts=11678|pts_time=11.678000|dts=11678|dts_time=11.678000|duration=33|duration_time=0.033000|size=1190|pos=510794|flags=__|data_hash=CRC32:a0206c90 -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|width=426|height=240|coded_width=426|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=71:40|pix_fmt=yuv420p|level=21|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=30/1|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=393929|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=351|extradata_hash=CRC32:07b85ca9|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 -stream|index=1|codec_name=aac|profile=1|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=22050|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=67874|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=252|extradata_hash=CRC32:d039c029|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|width=426|height=240|coded_width=426|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=71:40|pix_fmt=yuv420p|level=21|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=30/1|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=393929|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=351|extradata_size=39|extradata_hash=CRC32:07b85ca9|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=1|codec_name=aac|profile=1|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=22050|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=67874|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=252|extradata_size=2|extradata_hash=CRC32:d039c029|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=Enigma_Principles_of_Lust-part.flv|nb_streams=2|nb_programs=0|format_name=flv|start_time=0.000000|duration=210.209999|size=512000|bit_rate=19485|probe_score=100|tag:hasKeyframes=true|tag:hasMetadata=true|tag:datasize=11970544|tag:hasVideo=true|tag:canSeekToEnd=false|tag:lasttimestamp=210|tag:lastkeyframetimestamp=210|tag:audiosize=1791332|tag:hasAudio=true|tag:audiodelay=0|tag:videosize=10176110|tag:metadatadate=2011-02-27T11:00:33.125000Z|tag:metadatacreator=inlet media FLVTool2 v1.0.6 - http://www.inlet-media.de/flvtool2|tag:hasCuePoints=false diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie index cb34bd7f5c..2963de529d 100644 --- a/tests/ref/fate/mov-zombie +++ b/tests/ref/fate/mov-zombie @@ -194,5 +194,5 @@ frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|p packet|codec_type=video|stream_index=0|pts=197632|pts_time=2.195911|dts=191625|dts_time=2.129167|duration=3003|duration_time=0.033367|size=580|pos=101820|flags=__ frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|extradata_size=34|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264 side_data|side_data_type=Display Matrix|displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|rotation=0 diff --git a/tests/ref/fate/mxf-probe-d10 b/tests/ref/fate/mxf-probe-d10 index 6067f3ef30..b2692c6513 100644 --- a/tests/ref/fate/mxf-probe-d10 +++ b/tests/ref/fate/mxf-probe-d10 @@ -37,6 +37,7 @@ bits_per_raw_sample=N/A nb_frames=N/A nb_read_frames=N/A nb_read_packets=N/A +extradata_size=22 DISPOSITION:default=0 DISPOSITION:dub=0 DISPOSITION:original=0 diff --git a/tests/ref/fate/oggopus-demux b/tests/ref/fate/oggopus-demux index 450ca9f7d5..ab5ba2a93b 100644 --- a/tests/ref/fate/oggopus-demux +++ b/tests/ref/fate/oggopus-demux @@ -41,5 +41,5 @@ packet|codec_type=audio|stream_index=0|pts=36124|pts_time=0.752583|dts=36124|dts packet|codec_type=audio|stream_index=0|pts=37084|pts_time=0.772583|dts=37084|dts_time=0.772583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:06797ece packet|codec_type=audio|stream_index=0|pts=38044|pts_time=0.792583|dts=38044|dts_time=0.792583|duration=356|duration_time=0.007417|size=359|pos=841|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 |data_hash=CRC32:01ca3f8f -stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/48000|start_pts=0|start_time=0.000000|duration_ts=38756|duration=0.807417|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=41|extradata_hash=CRC32:58ba5ff3|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:ENCODER=opusenc from opus-tools 0.1.9|tag:ENCODER_OPTIONS=--discard-comments +stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/48000|start_pts=0|start_time=0.000000|duration_ts=38756|duration=0.807417|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=41|extradata_size=19|extradata_hash=CRC32:58ba5ff3|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:ENCODER=opusenc from opus-tools 0.1.9|tag:ENCODER_OPTIONS=--discard-comments format|filename=intro-partial.opus|nb_streams=1|nb_programs=0|format_name=ogg|start_time=0.000000|duration=0.807417|size=10250|bit_rate=101558|probe_score=100 diff --git a/tests/ref/fate/ts-demux b/tests/ref/fate/ts-demux index 8e7a81da41..9702feb0d6 100644 --- a/tests/ref/fate/ts-demux +++ b/tests/ref/fate/ts-demux @@ -41,7 +41,7 @@ packet|codec_type=audio|stream_index=2|pts=3912642700|pts_time=43473.807778|dts= packet|codec_type=video|stream_index=0|pts=3912686363|pts_time=43474.292922|dts=3912686363|dts_time=43474.292922|duration=1501|duration_time=0.016678|size=4944|pos=506660|flags=__|data_hash=CRC32:54a86cbb packet|codec_type=audio|stream_index=1|pts=3912644825|pts_time=43473.831389|dts=3912644825|dts_time=43473.831389|duration=2880|duration_time=0.032000|size=906|pos=474888|flags=K_|data_hash=CRC32:0893d398 packet|codec_type=audio|stream_index=2|pts=3912645580|pts_time=43473.839778|dts=3912645580|dts_time=43473.839778|duration=2880|duration_time=0.032000|size=354|pos=491808|flags=K_|data_hash=CRC32:f5963fa6 -stream|index=0|codec_name=mpeg2video|profile=4|codec_type=video|codec_tag_string=[2][0][0][0]|codec_tag=0x0002|width=1280|height=720|coded_width=0|coded_height=0|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=4|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|id=0x31|r_frame_rate=60000/1001|avg_frame_rate=60000/1001|time_base=1/90000|start_pts=3912669846|start_time=43474.109400|duration_ts=19519|duration=0.216878|bit_rate=15000000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=15|extradata_hash=CRC32:53134fa8|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=mpeg2video|profile=4|codec_type=video|codec_tag_string=[2][0][0][0]|codec_tag=0x0002|width=1280|height=720|coded_width=0|coded_height=0|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=4|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|id=0x31|r_frame_rate=60000/1001|avg_frame_rate=60000/1001|time_base=1/90000|start_pts=3912669846|start_time=43474.109400|duration_ts=19519|duration=0.216878|bit_rate=15000000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=15|extradata_size=150|extradata_hash=CRC32:53134fa8|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 side_data|side_data_type=CPB properties|max_bitrate=15000000|min_bitrate=0|avg_bitrate=0|buffer_size=9781248|vbv_delay=-1 stream|index=1|codec_name=ac3|profile=unknown|codec_type=audio|codec_tag_string=[4][0][0][0]|codec_tag=0x0004|sample_fmt=fltp|sample_rate=48000|channels=6|channel_layout=5.1(side)|bits_per_sample=0|id=0x34|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=3912633305|start_time=43473.703389|duration_ts=14400|duration=0.160000|bit_rate=384000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=5|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:language=eng stream|index=2|codec_name=ac3|profile=unknown|codec_type=audio|codec_tag_string=[4][0][0][0]|codec_tag=0x0004|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=0x35|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=3912634060|start_time=43473.711778|duration_ts=14400|duration=0.160000|bit_rate=192000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=5|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:language=es diff --git a/tests/ref/fate/ts-opus-demux b/tests/ref/fate/ts-opus-demux index 722fa74916..6513c0d4c2 100644 --- a/tests/ref/fate/ts-opus-demux +++ b/tests/ref/fate/ts-opus-demux @@ -1022,5 +1022,5 @@ packet|codec_type=audio|stream_index=0|pts=918000|pts_time=10.200000|dts=918000| |data_hash=CRC32:75113c11 packet|codec_type=audio|stream_index=0|pts=919800|pts_time=10.220000|dts=919800|dts_time=10.220000|duration=1800|duration_time=0.020000|size=759|pos=510984|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59fc266f -stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=Opus|codec_tag=0x7375704f|sample_fmt=fltp|sample_rate=48000|channels=8|channel_layout=7.1|bits_per_sample=0|id=0x44|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=919800|duration=10.220000|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=512|extradata_hash=CRC32:6d6089a7|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=Opus|codec_tag=0x7375704f|sample_fmt=fltp|sample_rate=48000|channels=8|channel_layout=7.1|bits_per_sample=0|id=0x44|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=919800|duration=10.220000|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=512|extradata_size=29|extradata_hash=CRC32:6d6089a7|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=test-8-7.1.opus-small.ts|nb_streams=1|nb_programs=1|format_name=mpegts|start_time=0.000000|duration=10.220000|size=512000|bit_rate=400782|probe_score=50 diff --git a/tests/ref/fate/ts-small-demux b/tests/ref/fate/ts-small-demux index 264d878d5b..1b0a21621b 100644 --- a/tests/ref/fate/ts-small-demux +++ b/tests/ref/fate/ts-small-demux @@ -145,5 +145,5 @@ packet|codec_type=video|stream_index=0|pts=552000|pts_time=6.133333|dts=552000|d packet|codec_type=video|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=6000|duration_time=0.066667|size=16|pos=15792|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:27b943ef packet|codec_type=video|stream_index=0|pts=564000|pts_time=6.266667|dts=564000|dts_time=6.266667|duration=6000|duration_time=0.066667|size=16|pos=16356|flags=__|data_hash=CRC32:f7116111 -stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|width=82|height=144|coded_width=82|coded_height=144|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=false|nal_length_size=0|id=0x100|r_frame_rate=15/1|avg_frame_rate=15/1|time_base=1/90000|start_pts=126000|start_time=1.400000|duration_ts=444000|duration=4.933333|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=74|extradata_hash=CRC32:e62cae27|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|width=82|height=144|coded_width=82|coded_height=144|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=false|nal_length_size=0|id=0x100|r_frame_rate=15/1|avg_frame_rate=15/1|time_base=1/90000|start_pts=126000|start_time=1.400000|duration_ts=444000|duration=4.933333|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=74|extradata_size=35|extradata_hash=CRC32:e62cae27|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=h264small.ts|nb_streams=1|nb_programs=1|format_name=mpegts|start_time=1.400000|duration=4.933333|size=16544|bit_rate=26828|probe_score=50 From d9f07a506d230321f826dcb50828e1d10e852b44 Mon Sep 17 00:00:00 2001 From: Ryoji Gyoda Date: Mon, 22 Nov 2021 02:06:20 +0900 Subject: [PATCH 309/894] avformat/fifo: avoid repeated scaling of timestamps on failure and recovery If fifo_thread_recover() succeeds immediately after fifo_thread_dispatch_message() fails, the dts of the packet is scaled twice, causing cur_dts to be abnormally large and "Application provided invalid, non monotonically increasing dts to muxer in stream" to occur repeatedly. Steps to reproduce: 1. ffmpeg -f lavfi -i testsrc -c:v libx264 -map 0:v -flags +global_header -f fifo -fifo_format flv -attempt_recovery 1 -recover_any_error 1 rtmp://example.com/livekey 2. set a breakpoint on fifo_thread_recover 3. force disconnect from the rtmp server 4. wait for break 5. reconnect to the rtmp server 6. resume execution of ffmpeg Signed-off-by: Ryoji Gyoda Signed-off-by: Marton Balint --- libavformat/fifo.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavformat/fifo.c b/libavformat/fifo.c index 51d7fa5b94..2ee6dde830 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -183,6 +183,7 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) AVFormatContext *avf2 = fifo->avf; AVRational src_tb, dst_tb; int ret, s_idx; + int64_t orig_pts, orig_dts, orig_duration; if (fifo->timeshift && pkt->dts != AV_NOPTS_VALUE) atomic_fetch_sub_explicit(&fifo->queue_duration, next_duration(avf, pkt, &ctx->last_received_dts), memory_order_relaxed); @@ -198,14 +199,23 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) } } + orig_pts = pkt->pts; + orig_dts = pkt->dts; + orig_duration = pkt->duration; s_idx = pkt->stream_index; src_tb = avf->streams[s_idx]->time_base; dst_tb = avf2->streams[s_idx]->time_base; av_packet_rescale_ts(pkt, src_tb, dst_tb); ret = av_write_frame(avf2, pkt); - if (ret >= 0) + if (ret >= 0) { av_packet_unref(pkt); + } else { + // avoid scaling twice + pkt->pts = orig_pts; + pkt->dts = orig_dts; + pkt->duration = orig_duration; + } return ret; } From 4913f05ccf70dc1470f284b9a32c0e66991f6029 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 26 Nov 2021 19:44:21 +0100 Subject: [PATCH 310/894] fftools/ffmpeg_opt: Don't duplicate array unnecessarily Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 3 --- fftools/ffmpeg.h | 7 ++++--- fftools/ffmpeg_opt.c | 43 ++++++++----------------------------------- 3 files changed, 12 insertions(+), 41 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 25360423b5..18302f3b5f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -555,9 +555,6 @@ static void ffmpeg_cleanup(int ret) avfilter_inout_free(&ofilter->out_tmp); av_freep(&ofilter->name); - av_freep(&ofilter->formats); - av_freep(&ofilter->channel_layouts); - av_freep(&ofilter->sample_rates); av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 21c63415d6..a20ca964fb 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -273,9 +273,10 @@ typedef struct OutputFilter { uint64_t channel_layout; // those are only set if no format is specified and the encoder gives us multiple options - int *formats; - uint64_t *channel_layouts; - int *sample_rates; + // They point directly to the relevant lists of the encoder. + const int *formats; + const uint64_t *channel_layouts; + const int *sample_rates; } OutputFilter; typedef struct FilterGraph { diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index debd13f3bd..4845dd18a3 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -2614,7 +2614,6 @@ loop_end: /* set the filter output constraints */ if (ost->filter) { OutputFilter *f = ost->filter; - int count; switch (ost->enc_ctx->codec_type) { case AVMEDIA_TYPE_VIDEO: f->frame_rate = ost->frame_rate; @@ -2622,51 +2621,25 @@ loop_end: f->height = ost->enc_ctx->height; if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { f->format = ost->enc_ctx->pix_fmt; - } else if (ost->enc->pix_fmts) { - count = 0; - while (ost->enc->pix_fmts[count] != AV_PIX_FMT_NONE) - count++; - f->formats = av_calloc(count + 1, sizeof(*f->formats)); - if (!f->formats) - exit_program(1); - memcpy(f->formats, ost->enc->pix_fmts, (count + 1) * sizeof(*f->formats)); + } else { + f->formats = ost->enc->pix_fmts; } break; case AVMEDIA_TYPE_AUDIO: if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { f->format = ost->enc_ctx->sample_fmt; - } else if (ost->enc->sample_fmts) { - count = 0; - while (ost->enc->sample_fmts[count] != AV_SAMPLE_FMT_NONE) - count++; - f->formats = av_calloc(count + 1, sizeof(*f->formats)); - if (!f->formats) - exit_program(1); - memcpy(f->formats, ost->enc->sample_fmts, (count + 1) * sizeof(*f->formats)); + } else { + f->formats = ost->enc->sample_fmts; } if (ost->enc_ctx->sample_rate) { f->sample_rate = ost->enc_ctx->sample_rate; - } else if (ost->enc->supported_samplerates) { - count = 0; - while (ost->enc->supported_samplerates[count]) - count++; - f->sample_rates = av_calloc(count + 1, sizeof(*f->sample_rates)); - if (!f->sample_rates) - exit_program(1); - memcpy(f->sample_rates, ost->enc->supported_samplerates, - (count + 1) * sizeof(*f->sample_rates)); + } else { + f->sample_rates = ost->enc->supported_samplerates; } if (ost->enc_ctx->channels) { f->channel_layout = av_get_default_channel_layout(ost->enc_ctx->channels); - } else if (ost->enc->channel_layouts) { - count = 0; - while (ost->enc->channel_layouts[count]) - count++; - f->channel_layouts = av_calloc(count + 1, sizeof(*f->channel_layouts)); - if (!f->channel_layouts) - exit_program(1); - memcpy(f->channel_layouts, ost->enc->channel_layouts, - (count + 1) * sizeof(*f->channel_layouts)); + } else { + f->channel_layouts = ost->enc->channel_layouts; } break; } From e22dff43e72a79bbf559fcc72f5a0f70b77eaff4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 27 Nov 2021 12:15:18 +0100 Subject: [PATCH 311/894] fftools/ffmpeg_opt: Don't set source_index redundantly It is already set in new_output_stream(). Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 4845dd18a3..a27263b879 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -2197,7 +2197,6 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, exit_program(1); } - ost->source_index = -1; ost->filter = ofilter; ofilter->ost = ost; From 1cdbccaa163eb3bd50403ecc75fc3da9d5d75c02 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Sep 2021 12:20:20 +0200 Subject: [PATCH 312/894] avcodec/qsvenc: Fix leak and crash when encoding H.264 due to A53_CC Since commit 3bbe0c210b05fc6fbd7b1d4bbd8479db7f2cf957, the Payloads array of every QSVFrame leaks as soon as the frame is reused; the leak is small and not very noticeable, but if there is an attempt to use said array the ensuing crash is much more noticeable. This happens when encoding H.264 with A53 CC side data. Furthermore, if said array can not be allocated at all, an AVFrame leaks. Fix all of this by not allocating the array separately at all; put it in QSVFrame instead and restore the Payloads array upon reusing the frame. Finally, use av_freep() instead of av_free() to free the payload entries. Reviewed-by: Xiang, Haihao Signed-off-by: Andreas Rheinhardt --- libavcodec/qsv_internal.h | 2 ++ libavcodec/qsvenc.c | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 8090b748b3..fe9d5319c4 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -76,6 +76,8 @@ typedef struct QSVFrame { mfxExtDecodedFrameInfo dec_info; mfxExtBuffer *ext_param; + mfxPayload *payloads[QSV_MAX_ENC_PAYLOAD]; ///< used for enc_ctrl.Payload + int queued; int used; diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 06f55604b5..66f79bb021 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1259,7 +1259,7 @@ static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl) if (enc_ctrl) { int i; for (i = 0; i < enc_ctrl->NumPayload && i < QSV_MAX_ENC_PAYLOAD; i++) { - av_free(enc_ctrl->Payload[i]); + av_freep(&enc_ctrl->Payload[i]); } enc_ctrl->NumPayload = 0; } @@ -1273,6 +1273,7 @@ static void clear_unused_frames(QSVEncContext *q) free_encoder_ctrl_payloads(&cur->enc_ctrl); //do not reuse enc_ctrl from previous frame memset(&cur->enc_ctrl, 0, sizeof(cur->enc_ctrl)); + cur->enc_ctrl.Payload = cur->payloads; if (cur->frame->format == AV_PIX_FMT_QSV) { av_frame_unref(cur->frame); } @@ -1309,11 +1310,7 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f) av_freep(&frame); return AVERROR(ENOMEM); } - frame->enc_ctrl.Payload = av_mallocz(sizeof(mfxPayload*) * QSV_MAX_ENC_PAYLOAD); - if (!frame->enc_ctrl.Payload) { - av_freep(&frame); - return AVERROR(ENOMEM); - } + frame->enc_ctrl.Payload = frame->payloads; *last = frame; *f = frame; @@ -1615,7 +1612,6 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) while (cur) { q->work_frames = cur->next; av_frame_free(&cur->frame); - av_free(cur->enc_ctrl.Payload); av_freep(&cur); cur = q->work_frames; } From e9e2157dda26a08113a146330682f29e6d2accb4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Sep 2021 14:05:45 +0200 Subject: [PATCH 313/894] avcodec/qsvenc: Fix leak of A53 data Up until now, it has only been freed when the QSVFrame is reused, so that the last one contained in it leaked at the end. Signed-off-by: Andreas Rheinhardt --- libavcodec/qsvenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 66f79bb021..e5d09752cb 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1612,6 +1612,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) while (cur) { q->work_frames = cur->next; av_frame_free(&cur->frame); + free_encoder_ctrl_payloads(&cur->enc_ctrl); av_freep(&cur); cur = q->work_frames; } From d47a986b7922f610acb6801620aa9b4fa9a2b243 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Sep 2021 14:28:10 +0200 Subject: [PATCH 314/894] avcodec/qsvenc: Properly flush the FIFO on close Freeing the new H.264 specific fields has been forgotten. (This leak only appears in case the encoder has not been completely drained.) Signed-off-by: Andreas Rheinhardt --- libavcodec/qsvenc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index e5d09752cb..26a94cd419 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1626,6 +1626,14 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL); +#if QSV_VERSION_ATLEAST(1, 26) + if (avctx->codec_id == AV_CODEC_ID_H264) { + mfxExtBuffer **enc_buf = bs->ExtParam; + mfxExtAVCEncodedFrameInfo *enc_info = (mfxExtAVCEncodedFrameInfo *)(*bs->ExtParam); + av_freep(&enc_info); + av_freep(&enc_buf); + } +#endif av_freep(&sync); av_freep(&bs); av_packet_unref(&pkt); From 8a18db3ec6af13c0a9889f1ef61d38cabc714813 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 27 Nov 2021 14:15:45 +0100 Subject: [PATCH 315/894] avformat/matroskaenc: Sort cues entries by pts Currently they are ordered as-written (i.e. by increasing position); in case av_interleaved_write_frame() is used, this is (mostly) the same as ordered by increasing dts. Yet the Matroska specification strongly recommends (SHOULD) that the CuePoints be sorted by CueTime. mkvalidator warns when they are not. Therefore this commit sorts them accordingly. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index f08ead0a96..8c4cf4024a 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -533,6 +533,7 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, { mkv_cues *cues = &mkv->cues; mkv_cuepoint *entries = cues->entries; + unsigned idx = cues->num_entries; if (ts < 0) return 0; @@ -542,11 +543,19 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, return AVERROR(ENOMEM); cues->entries = entries; - cues->entries[cues->num_entries].pts = ts; - cues->entries[cues->num_entries].stream_idx = stream; - cues->entries[cues->num_entries].cluster_pos = cluster_pos - mkv->segment_offset; - cues->entries[cues->num_entries].relative_pos = relative_pos; - cues->entries[cues->num_entries++].duration = duration; + /* Make sure the cues entries are sorted by pts. */ + while (idx > 0 && entries[idx - 1].pts > ts) + idx--; + memmove(&entries[idx + 1], &entries[idx], + (cues->num_entries - idx) * sizeof(entries[0])); + + entries[idx].pts = ts; + entries[idx].stream_idx = stream; + entries[idx].cluster_pos = cluster_pos - mkv->segment_offset; + entries[idx].relative_pos = relative_pos; + entries[idx].duration = duration; + + cues->num_entries++; return 0; } From d1b47f3bfcc625ca1cae210fc198dcbd54381a88 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 29 Nov 2021 15:29:11 +0100 Subject: [PATCH 316/894] avcodec/vaapi_encode: Fix segfault upon closing uninitialized encoder Fixes ticket #9537. Probably a regression since 2b3206891649f317c20993411efef4bee39ae784. Signed-off-by: Andreas Rheinhardt --- libavcodec/vaapi_encode.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index ec054ae701..3bf379b1a0 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -2366,6 +2366,11 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) VAStatus vas; int err; + ctx->va_config = VA_INVALID_ID; + ctx->va_context = VA_INVALID_ID; + + /* If you add something that can fail above this av_frame_alloc(), + * modify ff_vaapi_encode_close() accordingly. */ ctx->frame = av_frame_alloc(); if (!ctx->frame) { return AVERROR(ENOMEM); @@ -2377,9 +2382,6 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - ctx->va_config = VA_INVALID_ID; - ctx->va_context = VA_INVALID_ID; - ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); if (!ctx->input_frames_ref) { err = AVERROR(ENOMEM); @@ -2531,6 +2533,11 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic, *next; + /* We check ctx->frame to know whether ff_vaapi_encode_init() + * has been called and va_config/va_context initialized. */ + if (!ctx->frame) + return 0; + for (pic = ctx->pic_start; pic; pic = next) { next = pic->next; vaapi_encode_free(avctx, pic); From 12f8293c025f0a6103f2d0a05b05bffa9f4ff434 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Thu, 2 Dec 2021 01:41:55 +1000 Subject: [PATCH 317/894] avformat/scd: add demuxer Adds demuxer for Square Enux SCD files. Based off [1] and personal investigation. This has only been tested against Drakengard 3 (PS3) *_SCD.XXX files (big-endian). As it is highly likely that FFXIV (PC) files are little-endian, this demuxer is marked as experimental until this can be confirmed. [1]: http://ffxivexplorer.fragmenterworks.com/research/scd%20files.txt Reviewed-by: Peter Ross Reviewed-by: Andreas Rheinhardt Signed-off-by: Zane van Iperen --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/scd.c | 378 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 380 insertions(+) create mode 100644 libavformat/scd.c diff --git a/libavformat/Makefile b/libavformat/Makefile index a19d2e0c88..2b5caf9d33 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -501,6 +501,7 @@ OBJS-$(CONFIG_SBC_MUXER) += rawenc.o OBJS-$(CONFIG_SBG_DEMUXER) += sbgdec.o OBJS-$(CONFIG_SCC_DEMUXER) += sccdec.o subtitles.o OBJS-$(CONFIG_SCC_MUXER) += sccenc.o subtitles.o +OBJS-$(CONFIG_SCD_DEMUXER) += scd.o OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o OBJS-$(CONFIG_SDS_DEMUXER) += sdsdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index cbfadcb639..1054ac9667 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -392,6 +392,7 @@ extern const AVOutputFormat ff_sbc_muxer; extern const AVInputFormat ff_sbg_demuxer; extern const AVInputFormat ff_scc_demuxer; extern const AVOutputFormat ff_scc_muxer; +extern const AVInputFormat ff_scd_demuxer; extern const AVInputFormat ff_sdp_demuxer; extern const AVInputFormat ff_sdr2_demuxer; extern const AVInputFormat ff_sds_demuxer; diff --git a/libavformat/scd.c b/libavformat/scd.c new file mode 100644 index 0000000000..0ed5322a14 --- /dev/null +++ b/libavformat/scd.c @@ -0,0 +1,378 @@ +/* + * Square Enix SCD demuxer + * Copyright (C) 2021 Zane van Iperen (zane@zanevaniperen.com) + * + * Based off documentation: + * http://ffxivexplorer.fragmenterworks.com/research/scd%20files.txt + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/internal.h" +#include "libavutil/macros.h" +#include "libavutil/avassert.h" +#include "libavformat/internal.h" +#include "avformat.h" + +#define SCD_MAGIC ((uint64_t)MKBETAG('S', 'E', 'D', 'B') << 32 | \ + MKBETAG('S', 'S', 'C', 'F')) +#define SCD_MIN_HEADER_SIZE 20 +#define SCD_OFFSET_HEADER_SIZE 28 +#define SCD_TRACK_HEADER_SIZE 32 + +#define SCD_TRACK_ID_PCM 0 +#define SCD_TRACK_ID_OGG 6 +#define SCD_TRACK_ID_MP3 7 +#define SCD_TRACK_ID_MS_ADPCM 12 + +typedef struct SCDOffsetTable { + uint16_t count; + uint32_t offset; + uint32_t *entries; +} SCDOffsetTable; + +typedef struct SCDHeader { + uint64_t magic; /* SEDBSSCF */ + uint32_t version; /* Verison number. We only know about 3. */ + uint16_t unk1; /* Unknown, 260 in Drakengard 3, 1024 in FFXIV. */ + uint16_t header_size; /* Total size of this header. */ + uint32_t file_size; /* Is often 0, just ignore it. */ + + SCDOffsetTable table0; /* Table 0, no idea. 56 uint32's/entry. */ + SCDOffsetTable table1; /* Table 1, contains the track info. */ + SCDOffsetTable table2; /* Table 2, no idea. 40 uint32's/entry. */ + uint16_t unk2; /* Unknown, not a count. */ + uint32_t unk3; /* Unknown, not an offset. */ + uint32_t unk4; /* Unknown, offset to offset. */ +} SCDHeader; + +typedef struct SCDTrackHeader { + uint32_t length; + uint32_t num_channels; + uint32_t sample_rate; + uint32_t data_type; + uint32_t loop_start; + uint32_t loop_end; + uint32_t data_offset; /* Offset to data + this header. */ + uint32_t aux_count; + + uint32_t absolute_offset; + uint32_t bytes_read; +} SCDTrackHeader; + +typedef struct SCDDemuxContext { + SCDHeader hdr; + SCDTrackHeader *tracks; + int current_track; +} SCDDemuxContext; + +static int scd_probe(const AVProbeData *p) +{ + if (AV_RB64(p->buf) != SCD_MAGIC) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int scd_read_table(AVFormatContext *s, SCDOffsetTable *table) +{ + int64_t ret; + + if ((ret = avio_seek(s->pb, table->offset, SEEK_SET)) < 0) + return ret; + + if ((table->entries = av_calloc(table->count, sizeof(uint32_t))) == NULL) + return ret; + + if ((ret = avio_read(s->pb, (unsigned char*)table->entries, table->count * sizeof(uint32_t))) < 0) + return ret; + + for (size_t i = 0; i < table->count; i++) + table->entries[i] = AV_RB32(table->entries + i); + + av_log(s, AV_LOG_TRACE, "Table, size = %u, offset = %u\n", table->count, table->offset); + for (size_t i = 0; i < table->count; i++) + av_log(s, AV_LOG_TRACE, " [%02zu]: %u\n", i, table->entries[i]); + + return 0; +} + +static int scd_read_offsets(AVFormatContext *s) +{ + int64_t ret; + SCDDemuxContext *ctx = s->priv_data; + uint8_t buf[SCD_OFFSET_HEADER_SIZE]; + + if ((ret = avio_read(s->pb, buf, SCD_OFFSET_HEADER_SIZE)) < 0) + return ret; + + ctx->hdr.table0.count = AV_RB16(buf + 0); + ctx->hdr.table1.count = AV_RB16(buf + 2); + ctx->hdr.table2.count = AV_RB16(buf + 4); + ctx->hdr.unk2 = AV_RB16(buf + 6); + ctx->hdr.table0.offset = AV_RB32(buf + 8); + ctx->hdr.table1.offset = AV_RB32(buf + 12); + ctx->hdr.table2.offset = AV_RB32(buf + 16); + ctx->hdr.unk3 = AV_RB32(buf + 20); + ctx->hdr.unk4 = AV_RB32(buf + 24); + + if ((ret = scd_read_table(s, &ctx->hdr.table0)) < 0) + return ret; + + if ((ret = scd_read_table(s, &ctx->hdr.table1)) < 0) + return ret; + + if ((ret = scd_read_table(s, &ctx->hdr.table2)) < 0) + return ret; + + return 0; +} + +static int scd_read_track(AVFormatContext *s, SCDTrackHeader *track, int index) +{ + int64_t ret; + uint32_t hoffset; + AVStream *st; + AVCodecParameters *par; + SCDDemuxContext *ctx = s->priv_data; + uint8_t buf[SCD_TRACK_HEADER_SIZE]; + + /* Mark as experimental until I find more files from more than just one game. */ + if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(s, AV_LOG_ERROR, "SCD demuxing is experimental, " + "add '-strict %d' if you want to use it.\n", + FF_COMPLIANCE_EXPERIMENTAL); + return AVERROR_EXPERIMENTAL; + } + + hoffset = ctx->hdr.table1.entries[index]; + + if ((ret = avio_seek(s->pb, hoffset, SEEK_SET)) < 0) + return ret; + + if ((ret = avio_read(s->pb, buf, SCD_TRACK_HEADER_SIZE)) < 0) + return ret; + + track->length = AV_RB32(buf + 0); + track->num_channels = AV_RB32(buf + 4); + track->sample_rate = AV_RB32(buf + 8); + track->data_type = AV_RB32(buf + 12); + track->loop_start = AV_RB32(buf + 16); + track->loop_end = AV_RB32(buf + 20); + track->data_offset = AV_RB32(buf + 24); + track->aux_count = AV_RB32(buf + 28); + + /* Sanity checks */ + if (track->num_channels > 8 || track->sample_rate >= 192000 || + track->loop_start > track->loop_end) + return AVERROR_INVALIDDATA; + + track->absolute_offset = hoffset + SCD_TRACK_HEADER_SIZE + track->data_offset; + track->bytes_read = 0; + + /* Not sure what to do with these, it seems to be fine to ignore them. */ + if (track->aux_count != 0) + av_log(s, AV_LOG_DEBUG, "[%d] Track has %u auxillary chunk(s).\n", index, track->aux_count); + + if ((st = avformat_new_stream(s, NULL)) == NULL) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->channels = (int)track->num_channels; + par->sample_rate = (int)track->sample_rate; + st->index = index; + st->start_time = 0; + + /* TODO: Check this with other types. Drakengard 3 MP3s have 47999 instead of 48000. */ + if (track->data_type == SCD_TRACK_ID_MP3) + par->sample_rate += 1; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + if (av_dict_set_int(&st->metadata, "start", track->absolute_offset, 0) < 0) + return AVERROR(ENOMEM); + + if (av_dict_set_int(&st->metadata, "loop_start", track->loop_start, 0) < 0) + return AVERROR(ENOMEM); + + if (av_dict_set_int(&st->metadata, "loop_end", track->loop_end, 0) < 0) + return AVERROR(ENOMEM); + + switch(track->data_type) { + case SCD_TRACK_ID_PCM: + par->codec_id = AV_CODEC_ID_PCM_S16BE; + par->bits_per_coded_sample = 16; + par->block_align = par->bits_per_coded_sample * par->channels / 8; + break; + case SCD_TRACK_ID_MP3: + par->codec_id = AV_CODEC_ID_MP3; + ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; + break; + case SCD_TRACK_ID_OGG: + case SCD_TRACK_ID_MS_ADPCM: + default: + par->codec_id = AV_CODEC_ID_NONE; + avpriv_request_sample(s, "data type %u", track->data_type); + } + + return 0; +} + +static int scd_read_header(AVFormatContext *s) +{ + int64_t ret; + SCDDemuxContext *ctx = s->priv_data; + uint8_t buf[SCD_MIN_HEADER_SIZE]; + + if ((ret = avio_read(s->pb, buf, SCD_MIN_HEADER_SIZE)) < 0) + return ret; + + ctx->hdr.magic = AV_RB64(buf + 0); + ctx->hdr.version = AV_RB32(buf + 8); + ctx->hdr.unk1 = AV_RB16(buf + 12); + ctx->hdr.header_size = AV_RB16(buf + 14); + ctx->hdr.file_size = AV_RB32(buf + 16); + + if (ctx->hdr.magic != SCD_MAGIC) + return AVERROR_INVALIDDATA; + + if (ctx->hdr.version != 3) { + avpriv_request_sample(s, "SCD version %u", ctx->hdr.version); + return AVERROR_PATCHWELCOME; + } + + if (ctx->hdr.header_size < SCD_MIN_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + if ((ret = avio_skip(s->pb, ctx->hdr.header_size - SCD_MIN_HEADER_SIZE)) < 0) + return ret; + + if ((ret = scd_read_offsets(s)) < 0) + return ret; + + ctx->tracks = av_calloc(ctx->hdr.table1.count, sizeof(SCDTrackHeader)); + if (ctx->tracks == NULL) + return AVERROR(ENOMEM); + + for (int i = 0; i < ctx->hdr.table1.count; i++) { + if ((ret = scd_read_track(s, ctx->tracks + i, i)) < 0) + return ret; + } + + if (ctx->hdr.table1.count == 0) + return 0; + + if ((ret = avio_seek(s->pb, ctx->tracks[0].absolute_offset, SEEK_SET)) < 0) + return ret; + + return 0; +} + +static int scd_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + SCDDemuxContext *ctx = s->priv_data; + AVCodecParameters *par; + + /* Streams aren't interleaved, round-robin them. */ + for (int i = 0; i < ctx->hdr.table1.count; i++) { + int64_t ret; + int size; + SCDTrackHeader *trk; + + ctx->current_track %= ctx->hdr.table1.count; + + trk = ctx->tracks + ctx->current_track; + par = s->streams[ctx->current_track]->codecpar; + + if (trk->bytes_read >= trk->length) + continue; + + if ((ret = avio_seek(s->pb, trk->absolute_offset + trk->bytes_read, SEEK_SET)) < 0) + return ret; + + switch(trk->data_type) { + case SCD_TRACK_ID_PCM: + size = par->block_align; + break; + case SCD_TRACK_ID_MP3: + default: + size = FFMIN(trk->length - trk->bytes_read, 4096); + break; + } + + ret = av_get_packet(s->pb, pkt, size); + if (ret == AVERROR_EOF) { + trk->length = trk->bytes_read; + continue; + } else if (ret < 0) { + return ret; + } + + if (trk->data_type == SCD_TRACK_ID_PCM) { + pkt->pts = trk->bytes_read / (par->channels * sizeof(uint16_t)); + pkt->duration = size / (par->channels * sizeof(int16_t)); + } + + trk->bytes_read += ret; + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + pkt->stream_index = ctx->current_track; + + ctx->current_track++; + return 0; + } + + return AVERROR_EOF; +} + +static int scd_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + SCDDemuxContext *ctx = s->priv_data; + + if (pts != 0) + return AVERROR(EINVAL); + + for(int i = 0; i < ctx->hdr.table1.count; ++i) + ctx->tracks[i].bytes_read = 0; + + return 0; +} + +static int scd_read_close(AVFormatContext *s) +{ + SCDDemuxContext *ctx = s->priv_data; + + av_freep(&ctx->hdr.table0.entries); + av_freep(&ctx->hdr.table1.entries); + av_freep(&ctx->hdr.table2.entries); + av_freep(&ctx->tracks); + return 0; +} + +const AVInputFormat ff_scd_demuxer = { + .name = "scd", + .long_name = NULL_IF_CONFIG_SMALL("Square Enix SCD"), + .priv_data_size = sizeof(SCDDemuxContext), + .flags_internal = FF_FMT_INIT_CLEANUP, + .read_probe = scd_probe, + .read_header = scd_read_header, + .read_packet = scd_read_packet, + .read_seek = scd_seek, + .read_close = scd_read_close, +}; From 07f8f78a5fb8b6a28f7b9d79fae6e411a17114ee Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Wed, 1 Dec 2021 11:52:19 +0800 Subject: [PATCH 318/894] configure: Add support for loongarch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For la464 cpu: ./configure --cpu=la464 With cross-compiler: ./configure --cross-prefix=loongarch64-linux-gnu- \ --enable-cross-compile --arch=loongarch64 \ --target-os=linux --cpu=la464 Reviewed-by: 陈昊 Signed-off-by: Michael Niedermayer --- Changelog | 1 + configure | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/Changelog b/Changelog index 56faa7f9f5..648079ab64 100644 --- a/Changelog +++ b/Changelog @@ -35,6 +35,7 @@ version : - bitpacked encoder - VideoToolbox VP9 hwaccel - VideoToolbox ProRes hwaccel +- support loongarch. version 4.4: diff --git a/configure b/configure index d8b5be8bbb..aa94c39419 100755 --- a/configure +++ b/configure @@ -2032,6 +2032,9 @@ ARCH_LIST=" avr32_uc bfin ia64 + loongarch + loongarch32 + loongarch64 m68k mips mips64 @@ -4959,6 +4962,9 @@ case "$arch" in arm*|iPad*|iPhone*) arch="arm" ;; + loongarch*) + arch="loongarch" + ;; mips*|IP*) case "$arch" in *el) @@ -5106,6 +5112,18 @@ elif enabled bfin; then cpuflags="-mcpu=$cpu" +elif enabled loongarch; then + + enable local_aligned + enable simd_align_32 + enable fast_64bit + enable fast_clz + enable fast_unaligned + case $cpu in + la464) + cpuflags="-march=$cpu" + ;; + esac elif enabled mips; then if [ "$cpu" != "generic" ]; then @@ -5362,6 +5380,11 @@ case "$arch" in aarch64|alpha|ia64) enabled shared && enable_weak pic ;; + loongarch) + check_64bit loongarch32 loongarch64 + enabled loongarch64 && disable loongarch32 + enabled shared && enable_weak pic + ;; mips) check_64bit mips mips64 '_MIPS_SIM > 1' enabled shared && enable_weak pic From afcb36b7e54727d533b45303b36fa0d13ce02797 Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Wed, 1 Dec 2021 11:52:20 +0800 Subject: [PATCH 319/894] avcodec: [loongarch] optimize get_cabac. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decoding 1080P H264 on 2.5Ghz 3A5000: 165fps==>168fps. Testing command: ffmpeg -i ***.mp4 -f rawvideo -y /dev/null -an Reviewed-by: 陈昊 Signed-off-by: Michael Niedermayer --- libavcodec/cabac_functions.h | 3 + libavcodec/loongarch/cabac.h | 238 +++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 libavcodec/loongarch/cabac.h diff --git a/libavcodec/cabac_functions.h b/libavcodec/cabac_functions.h index 46af921822..2f2d48a8f8 100644 --- a/libavcodec/cabac_functions.h +++ b/libavcodec/cabac_functions.h @@ -49,6 +49,9 @@ #if ARCH_MIPS # include "mips/cabac.h" #endif +#if ARCH_LOONGARCH64 +# include "loongarch/cabac.h" +#endif static const uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET; static const uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET; diff --git a/libavcodec/loongarch/cabac.h b/libavcodec/loongarch/cabac.h new file mode 100644 index 0000000000..e1c946fe16 --- /dev/null +++ b/libavcodec/loongarch/cabac.h @@ -0,0 +1,238 @@ +/* + * Loongson optimized cabac + * + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Gu Xiwei(guxiwei-hf@loongson.cn) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_CABAC_H +#define AVCODEC_LOONGARCH_CABAC_H + +#include "libavcodec/cabac.h" +#include "config.h" + +#define GET_CABAC_LOONGARCH_UNCBSR \ + "ld.bu %[bit], %[state], 0x0 \n\t" \ + "andi %[tmp0], %[c_range], 0xC0 \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "add.d %[tmp0], %[tmp0], %[tables] \n\t" \ + "add.d %[tmp0], %[tmp0], %[bit] \n\t" \ + /* tmp1: RangeLPS */ \ + "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t" \ + \ + "sub.d %[c_range], %[c_range], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[c_range], 0x11 \n\t" \ + "bge %[tmp0], %[c_low], 1f \n\t" \ + "move %[c_range], %[tmp1] \n\t" \ + "nor %[bit], %[bit], %[bit] \n\t" \ + "sub.d %[c_low], %[c_low], %[tmp0] \n\t" \ + \ + "1: \n\t" \ + /* tmp1: *state */ \ + "add.d %[tmp0], %[tables], %[bit] \n\t" \ + "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t" \ + /* tmp2: lps_mask */ \ + "add.d %[tmp0], %[tables], %[c_range] \n\t" \ + "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t" \ + \ + "andi %[bit], %[bit], 0x01 \n\t" \ + "st.b %[tmp1], %[state], 0x0 \n\t" \ + "sll.d %[c_range], %[c_range], %[tmp2] \n\t" \ + "sll.d %[c_low], %[c_low], %[tmp2] \n\t" \ + \ + "and %[tmp1], %[c_low], %[cabac_mask] \n\t" \ + "bnez %[tmp1], 1f \n\t" \ + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" \ + "ctz.d %[tmp0], %[c_low] \n\t" \ + "addi.d %[tmp2], %[tmp0], -16 \n\t" \ + "revb.2h %[tmp0], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t" \ + "sll.d %[tmp0], %[tmp0], %[tmp2] \n\t" \ + "add.d %[c_low], %[c_low], %[tmp0] \n\t" \ + "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" \ + "1: \n\t" \ + +#define GET_CABAC_LOONGARCH \ + "ld.bu %[bit], %[state], 0x0 \n\t" \ + "andi %[tmp0], %[c_range], 0xC0 \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "add.d %[tmp0], %[tmp0], %[tables] \n\t" \ + "add.d %[tmp0], %[tmp0], %[bit] \n\t" \ + /* tmp1: RangeLPS */ \ + "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t" \ + \ + "sub.d %[c_range], %[c_range], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[c_range], 0x11 \n\t" \ + "bge %[tmp0], %[c_low], 1f \n\t" \ + "move %[c_range], %[tmp1] \n\t" \ + "nor %[bit], %[bit], %[bit] \n\t" \ + "sub.d %[c_low], %[c_low], %[tmp0] \n\t" \ + \ + "1: \n\t" \ + /* tmp1: *state */ \ + "add.d %[tmp0], %[tables], %[bit] \n\t" \ + "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t" \ + /* tmp2: lps_mask */ \ + "add.d %[tmp0], %[tables], %[c_range] \n\t" \ + "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t" \ + \ + "andi %[bit], %[bit], 0x01 \n\t" \ + "st.b %[tmp1], %[state], 0x0 \n\t" \ + "sll.d %[c_range], %[c_range], %[tmp2] \n\t" \ + "sll.d %[c_low], %[c_low], %[tmp2] \n\t" \ + \ + "and %[tmp1], %[c_low], %[cabac_mask] \n\t" \ + "bnez %[tmp1], 1f \n\t" \ + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" \ + "ctz.d %[tmp0], %[c_low] \n\t" \ + "addi.d %[tmp2], %[tmp0], -16 \n\t" \ + "revb.2h %[tmp0], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t" \ + "sll.d %[tmp0], %[tmp0], %[tmp2] \n\t" \ + \ + "add.d %[c_low], %[c_low], %[tmp0] \n\t" \ + \ + "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" \ + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" \ + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" \ + "1: \n\t" \ + +#define get_cabac_inline get_cabac_inline_loongarch +static av_always_inline +int get_cabac_inline_loongarch(CABACContext *c, uint8_t * const state) +{ + int64_t tmp0, tmp1, tmp2, bit; + + __asm__ volatile ( +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), + [c_bytestream]"+&r"(c->bytestream) + : [state]"r"(state), [tables]"r"(ff_h264_cabac_tables), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [lps_off]"i"(H264_LPS_RANGE_OFFSET), + [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), + [norm_off]"i"(H264_NORM_SHIFT_OFFSET), + [cabac_mask]"r"(CABAC_MASK) + : "memory" + ); + + return bit; +} + +#define get_cabac_bypass get_cabac_bypass_loongarch +static av_always_inline int get_cabac_bypass_loongarch(CABACContext *c) +{ + int64_t tmp0, tmp1, tmp2; + int res = 0; + __asm__ volatile( + "slli.d %[c_low], %[c_low], 0x01 \n\t" + "and %[tmp0], %[c_low], %[cabac_mask] \n\t" + "bnez %[tmp0], 1f \n\t" + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" +#if UNCHECKED_BITSTREAM_READER + "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" +#else + "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" +#endif + "revb.2h %[tmp1], %[tmp1] \n\t" + "slli.d %[tmp1], %[tmp1], 0x01 \n\t" + "sub.d %[tmp1], %[tmp1], %[cabac_mask] \n\t" + "add.d %[c_low], %[c_low], %[tmp1] \n\t" + "1: \n\t" + "slli.d %[tmp1], %[c_range], 0x11 \n\t" + "slt %[tmp0], %[c_low], %[tmp1] \n\t" + "sub.d %[tmp1], %[c_low], %[tmp1] \n\t" + "masknez %[tmp2], %[one], %[tmp0] \n\t" + "maskeqz %[res], %[res], %[tmp0] \n\t" + "or %[res], %[res], %[tmp2] \n\t" + "masknez %[tmp2], %[tmp1], %[tmp0] \n\t" + "maskeqz %[c_low], %[c_low], %[tmp0] \n\t" + "or %[c_low], %[c_low], %[tmp2] \n\t" + : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), + [c_bytestream]"+&r"(c->bytestream), [res]"+&r"(res) + : [cabac_mask]"r"(CABAC_MASK), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [one]"r"(0x01) + : "memory" + ); + return res; +} + +#define get_cabac_bypass_sign get_cabac_bypass_sign_loongarch +static av_always_inline +int get_cabac_bypass_sign_loongarch(CABACContext *c, int val) +{ + int64_t tmp0, tmp1; + int res = val; + __asm__ volatile( + "slli.d %[c_low], %[c_low], 0x01 \n\t" + "and %[tmp0], %[c_low], %[cabac_mask] \n\t" + "bnez %[tmp0], 1f \n\t" + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" +#if UNCHECKED_BITSTREAM_READER + "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" +#else + "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" +#endif + "revb.2h %[tmp1], %[tmp1] \n\t" + "slli.d %[tmp1], %[tmp1], 0x01 \n\t" + "sub.d %[tmp1], %[tmp1], %[cabac_mask] \n\t" + "add.d %[c_low], %[c_low], %[tmp1] \n\t" + "1: \n\t" + "slli.d %[tmp1], %[c_range], 0x11 \n\t" + "slt %[tmp0], %[c_low], %[tmp1] \n\t" + "sub.d %[tmp1], %[c_low], %[tmp1] \n\t" + "masknez %[tmp1], %[tmp1], %[tmp0] \n\t" + "maskeqz %[c_low], %[c_low], %[tmp0] \n\t" + "or %[c_low], %[c_low], %[tmp1] \n\t" + "sub.d %[tmp1], %[zero], %[res] \n\t" + "maskeqz %[tmp1], %[tmp1], %[tmp0] \n\t" + "masknez %[res], %[res], %[tmp0] \n\t" + "or %[res], %[res], %[tmp1] \n\t" + : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [res]"+&r"(res), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), + [c_bytestream]"+&r"(c->bytestream) + : [cabac_mask]"r"(CABAC_MASK), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [zero]"r"(0x0) + : "memory" + ); + + return res; +} +#endif /* AVCODEC_LOONGARCH_CABAC_H */ From 024e934480a34ff534020f1617c94a7212f88a0f Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Wed, 1 Dec 2021 11:52:21 +0800 Subject: [PATCH 320/894] avcodec: [loongarch] Optimize decode_significance/_8x8_loongarch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decoding 1080P H264 from 168fps to 170fps. Signed-off-by: Shiyou Yin Reviewed-by: 陈昊 Signed-off-by: Michael Niedermayer --- libavcodec/h264_cabac.c | 2 + libavcodec/loongarch/h264_cabac.c | 140 ++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 libavcodec/loongarch/h264_cabac.c diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index 973b3419c4..040fa0a257 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -42,6 +42,8 @@ #if ARCH_X86 #include "x86/h264_cabac.c" +#elif ARCH_LOONGARCH64 +#include "loongarch/h264_cabac.c" #endif /* Cabac pre state table */ diff --git a/libavcodec/loongarch/h264_cabac.c b/libavcodec/loongarch/h264_cabac.c new file mode 100644 index 0000000000..d88743bed7 --- /dev/null +++ b/libavcodec/loongarch/h264_cabac.c @@ -0,0 +1,140 @@ +/* + * Loongson optimized cabac + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/cabac.h" +#include "cabac.h" + +#define decode_significance decode_significance_loongarch +static int decode_significance_loongarch(CABACContext *c, int max_coeff, + uint8_t *significant_coeff_ctx_base, int *index, int64_t last_off) +{ + void *end = significant_coeff_ctx_base + max_coeff - 1; + int64_t minusstart = -(int64_t)significant_coeff_ctx_base; + int64_t minusindex = 4 - (int64_t)index; + int64_t bit, tmp0, tmp1, tmp2, one = 1; + uint8_t *state = significant_coeff_ctx_base; + + __asm__ volatile( + "3:" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "blt %[bit], %[one], 4f \n\t" + "add.d %[state], %[state], %[last_off] \n\t" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "sub.d %[state], %[state], %[last_off] \n\t" + "add.d %[tmp0], %[state], %[minusstart] \n\t" + "st.w %[tmp0], %[index], 0 \n\t" + "bge %[bit], %[one], 5f \n\t" + "addi.d %[index], %[index], 4 \n\t" + "4: \n\t" + "addi.d %[state], %[state], 1 \n\t" + "blt %[state], %[end], 3b \n\t" + "add.d %[tmp0], %[state], %[minusstart] \n\t" + "st.w %[tmp0], %[index], 0 \n\t" + "5: \n\t" + "add.d %[tmp0], %[index], %[minusindex] \n\t" + "srli.d %[tmp0], %[tmp0], 2 \n\t" + : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), [state]"+&r"(state), + [c_bytestream]"+&r"(c->bytestream), [index]"+&r"(index) + : [tables]"r"(ff_h264_cabac_tables), [end]"r"(end), [one]"r"(one), + [minusstart]"r"(minusstart), [minusindex]"r"(minusindex), + [last_off]"r"(last_off), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [lps_off]"i"(H264_LPS_RANGE_OFFSET), + [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), + [norm_off]"i"(H264_NORM_SHIFT_OFFSET), + [cabac_mask]"r"(CABAC_MASK) + : "memory" + ); + + return (int)tmp0; +} + +#define decode_significance_8x8 decode_significance_8x8_loongarch +static int decode_significance_8x8_loongarch( + CABACContext *c, uint8_t *significant_coeff_ctx_base, + int *index, uint8_t *last_coeff_ctx_base, const uint8_t *sig_off) +{ + int64_t minusindex = 4 - (int64_t)index; + int64_t bit, tmp0, tmp1, tmp2, one = 1, end = 63, last = 0; + uint8_t *state = 0; + int64_t flag_offset = H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET; + + __asm__ volatile( + "3: \n\t" + "ldx.bu %[tmp0], %[sig_off], %[last] \n\t" + "add.d %[state], %[tmp0], %[significant_coeff_ctx_base] \n\t" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "blt %[bit], %[one], 4f \n\t" + "add.d %[tmp0], %[tables], %[flag_offset] \n\t" + "ldx.bu %[tmp1], %[tmp0], %[last] \n\t" + "add.d %[state], %[tmp1], %[last_coeff_ctx_base] \n\t" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "st.w %[last], %[index], 0 \n\t" + "bge %[bit], %[one], 5f \n\t" + "addi.d %[index], %[index], 4 \n\t" + "4: \n\t" + "addi.d %[last], %[last], 1 \n\t" + "blt %[last], %[end], 3b \n\t" + "st.w %[last], %[index], 0 \n\t" + "5: \n\t" + "add.d %[tmp0], %[index], %[minusindex] \n\t" + "srli.d %[tmp0], %[tmp0], 2 \n\t" + : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), + [tmp2]"=&r"(tmp2), [c_range]"+&r"(c->range), + [c_low]"+&r"(c->low), [state]"+&r"(state), [last]"+&r"(last), + [c_bytestream]"+&r"(c->bytestream), [index]"+&r"(index) + : [tables]"r"(ff_h264_cabac_tables), [end]"r"(end), + [one]"r"(one), [minusindex]"r"(minusindex), + [last_coeff_ctx_base]"r"(last_coeff_ctx_base), + [flag_offset]"r"(flag_offset), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [lps_off]"i"(H264_LPS_RANGE_OFFSET), [sig_off]"r"(sig_off), + [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), + [norm_off]"i"(H264_NORM_SHIFT_OFFSET), + [cabac_mask]"r"(CABAC_MASK), + [significant_coeff_ctx_base]"r"(significant_coeff_ctx_base) + ); + + return (int)tmp0; +} From 6e34d947978867789ca563aaced26b166753b062 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 27 Nov 2021 21:00:07 +0100 Subject: [PATCH 321/894] avcodec/gemdec: Check tag & planes before image allocation Fixes: Timeout Fixes: 41083/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_GEM_fuzzer-5843826518917120 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Peter Ross Signed-off-by: Michael Niedermayer --- libavcodec/gemdec.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c index 2464dda8a7..eee21a50d4 100644 --- a/libavcodec/gemdec.c +++ b/libavcodec/gemdec.c @@ -157,6 +157,14 @@ static int gem_decode_frame(AVCodecContext *avctx, if (header_size >= 11) tag = bytestream2_peek_be32(&gb); + if (tag == AV_RB32("STTT") || tag == AV_RB32("TIMG") || tag == AV_RB32("XIMG") || + planes == 1 || planes == 2 || planes == 3 || planes == 4 || + planes == 8 || planes == 16 || planes == 24) { + } else { + avpriv_request_sample(avctx, "planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; @@ -236,9 +244,6 @@ static int gem_decode_frame(AVCodecContext *avctx, planes = 1; row_width = avctx->width * pixel_size; put_lines = put_lines_bytes; - } else { - avpriv_request_sample(avctx, "planes=%d", planes); - return AVERROR_PATCHWELCOME; } ret = av_reallocp_array(&avctx->priv_data, planes, row_width); From db27a350129aa9f1fe5670cbf9118a78193d89cf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 30 Nov 2021 19:20:57 +0100 Subject: [PATCH 322/894] tools/target_dec_fuzzer: Adjust DXA threshold Fixes: Timeout Fixes: 40203/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXA_fuzzer-4587923496894464 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 15466a76d5..e27c45ddaa 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -160,6 +160,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_DIRAC: maxpixels /= 8192; break; case AV_CODEC_ID_DST: maxsamples /= 1<<20; break; case AV_CODEC_ID_DVB_SUBTITLE: av_dict_set_int(&opts, "compute_clut", -2, 0); break; + case AV_CODEC_ID_DXA: maxpixels /= 32; break; case AV_CODEC_ID_DXV: maxpixels /= 32; break; case AV_CODEC_ID_FFWAVESYNTH: maxsamples /= 16384; break; case AV_CODEC_ID_FLAC: maxsamples /= 1024; break; From 96caa01f130526cb420d0706a40fb63695153128 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 30 Nov 2021 19:46:17 +0100 Subject: [PATCH 323/894] avcodec/vp3: Check version in all cases when VP4 code is not built Fixes: out of array read Fixes: 40284/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VP3_fuzzer-4599568176644096 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Peter Ross Signed-off-by: Michael Niedermayer --- libavcodec/vp3.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 16726080b3..5b9ba60f49 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2685,7 +2685,14 @@ static int vp3_decode_frame(AVCodecContext *avctx, skip_bits(&gb, 4); /* width code */ skip_bits(&gb, 4); /* height code */ if (s->version) { - s->version = get_bits(&gb, 5); + int version = get_bits(&gb, 5); +#if !CONFIG_VP4_DECODER + if (version >= 2) { + av_log(avctx, AV_LOG_ERROR, "This build does not support decoding VP4.\n"); + return AVERROR_DECODER_NOT_FOUND; + } +#endif + s->version = version; if (avctx->frame_number == 0) av_log(s->avctx, AV_LOG_DEBUG, "VP version: %d\n", s->version); From c1818cb9471c0ab8345a023dc16d6b0c8c2ee000 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 25 Nov 2021 14:06:01 -0300 Subject: [PATCH 324/894] ffmpeg: fix usage of -shortest in codec copy scenarios Don't mark all streams as finished, instead make sync_opts keep track of the stream's duration, and set recording_time to it, same as in transcoding paths. Fixes tickets #9512 and #9513. Signed-off-by: James Almer --- fftools/ffmpeg.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 18302f3b5f..cfb04d5eff 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -871,10 +871,11 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u static void close_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; + AVRational time_base = ost->stream_copy ? ost->mux_timebase : ost->enc_ctx->time_base; ost->finished |= ENCODER_FINISHED; if (of->shortest) { - int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, ost->enc_ctx->time_base, AV_TIME_BASE_Q); + int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, time_base, AV_TIME_BASE_Q); of->recording_time = FFMIN(of->recording_time, end); } } @@ -1483,13 +1484,13 @@ static void do_video_stats(OutputStream *ost, int frame_size) static void finish_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; - int i; + AVRational time_base = ost->stream_copy ? ost->mux_timebase : ost->enc_ctx->time_base; ost->finished = ENCODER_FINISHED | MUXER_FINISHED; if (of->shortest) { - for (i = 0; i < of->ctx->nb_streams; i++) - output_streams[of->ost_index + i]->finished = ENCODER_FINISHED | MUXER_FINISHED; + int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, time_base, AV_TIME_BASE_Q); + of->recording_time = FFMIN(of->recording_time, end); } } @@ -2086,10 +2087,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } } - /* force the input stream PTS */ - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) - ost->sync_opts++; - if (av_packet_ref(opkt, pkt) < 0) exit_program(1); @@ -2113,6 +2110,8 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); + ost->sync_opts += opkt->duration; + output_packet(of, opkt, ost, 0); } From bb0a28560d6c50f2fa1240e77ee387d610c6c74a Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 1 Dec 2021 11:01:11 -0300 Subject: [PATCH 325/894] fate/ffmpeg: add tests for shortest option Signed-off-by: James Almer --- tests/fate/ffmpeg.mak | 19 ++++++ tests/ref/fate/copy-shortest1 | 123 +++++++++++++++++++++++++++++++++ tests/ref/fate/copy-shortest2 | 124 ++++++++++++++++++++++++++++++++++ tests/ref/fate/shortest | 123 +++++++++++++++++++++++++++++++++ 4 files changed, 389 insertions(+) create mode 100644 tests/ref/fate/copy-shortest1 create mode 100644 tests/ref/fate/copy-shortest2 create mode 100644 tests/ref/fate/shortest diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 4dfb77d250..b43db423a9 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -86,6 +86,9 @@ fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ -guess_layout_max 0 -f s32le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) \ -f ac3 -flags +bitexact -c ac3_fixed +FATE_FFMPEG-$(call ALLYES, SINE_FILTER AMIX_FILTER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-shortest +fate-shortest: tests/data/vsynth_lena.yuv +fate-shortest: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -c:v mpeg4 -c:a ac3_fixed -shortest FATE_STREAMCOPY-$(call ALLYES, EAC3_DEMUXER MOV_MUXER) += fate-copy-trac3074 fate-copy-trac3074: $(SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 @@ -131,6 +134,22 @@ FATE_STREAMCOPY-$(CONFIG_FLV_DEMUXER) += fate-ffmpeg-streamloop fate-ffmpeg-streamloop: $(SAMPLES)/flv/streamloop.flv fate-ffmpeg-streamloop: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/streamloop.flv -c copy +FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER AC3_FIXED_ENCODER) += fate-copy-shortest1 +fate-copy-shortest1: tests/data/vsynth_lena.yuv +fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest + +tests/data/audio_shorter_than_video.nut: TAG = GEN +tests/data/audio_shorter_than_video.nut: tests/data/vsynth_lena.yuv +tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -c:v mpeg4 \ + -f lavfi -i "sine=1000:d=1" -c:a pcm_s16le \ + -y $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut 2>/dev/null + +FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest2 +fate-copy-shortest2: tests/data/audio_shorter_than_video.nut +fate-copy-shortest2: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 1:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest + fate-streamcopy: $(FATE_STREAMCOPY-yes) FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER MATROSKA_MUXER) += fate-rgb24-mkv diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1 new file mode 100644 index 0000000000..c4d4a0c0f9 --- /dev/null +++ b/tests/ref/fate/copy-shortest1 @@ -0,0 +1,123 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: ac3 +#sample_rate 1: 44100 +#channel_layout 1: 4 +#channel_layout_name 1: mono +#stream#, dts, pts, duration, size, hash +1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce +0, 0, 0, 1, 152064, 64ffa0d5a62ddf325a92195fda238dd4 +1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 +0, 1, 1, 1, 152064, d17acf3ef7ce8c8d0ac1c3b89d77d6dc +1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 +0, 2, 2, 1, 152064, c08a06d8a267f8fb94e64362f8d5f311 +1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade +0, 3, 3, 1, 152064, 029eea5860e7b326dd7e10e2be64a098 +1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 +0, 4, 4, 1, 152064, aabca39f06e9b19f84560db8a43de0cf +1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 +0, 5, 5, 1, 152064, 6681a5e5af601bbf0e0318d1f240a955 +1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 +1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 +0, 6, 6, 1, 152064, 35f466e17c2b3a9de281a0405dd9bc5c +1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 +0, 7, 7, 1, 152064, a6af204b9a1a091f5b2e8981a73df3aa +1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 +0, 8, 8, 1, 152064, c037c758227f61da1faffb149af750a5 +1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae +0, 9, 9, 1, 152064, 76d1d9e8374070db553c9a89482dc165 +1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 +0, 10, 10, 1, 152064, 9361f2dac0279cb019948694daeff0b1 +1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 +0, 11, 11, 1, 152064, 97a544d9c6b8f50afd15fe6dfd4c22a2 +1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c +0, 12, 12, 1, 152064, dec68cf40dcf205f739b909d178310cf +1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb +1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 +0, 13, 13, 1, 152064, 6afd4a8feb3f8fc1825d0da292013472 +1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 +0, 14, 14, 1, 152064, d7297857fbfcf3fe0157eafe4114f957 +1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 +0, 15, 15, 1, 152064, 3e004f5a07599daec056189f8ab879e6 +1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc +0, 16, 16, 1, 152064, fb8dfc19d47a925f6bbcb8a334a80f2b +1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 +0, 17, 17, 1, 152064, 8aad1267917e26696593b35aabeaae60 +1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 +0, 18, 18, 1, 152064, dce70f7213f70a248c1ffd78244a0757 +1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb +0, 19, 19, 1, 152064, fbe3fa678d3b8d48f1d7fd45cb869241 +1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b +1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 +0, 20, 20, 1, 152064, eef85510c95abc810269888dd5037e38 +1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d +0, 21, 21, 1, 152064, 30ccae29a495eb6157930a3db50ad171 +1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 +0, 22, 22, 1, 152064, 5cf0001156e38570b830509ec727f956 +1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae +0, 23, 23, 1, 152064, 6686944299e7aea38756b8321a5ad5fd +1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed +0, 24, 24, 1, 152064, e618b079c3083cc4f4b080b6c6b8f645 +1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd +0, 25, 25, 1, 152064, ebf84cc4a497cc56d39e10bed3c0418e +1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 +1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 +0, 26, 26, 1, 152064, 10ee72dac1749c7b68f8a9318270953a +1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 +0, 27, 27, 1, 152064, 32e3028c0bf5e27d86972a51ce33927c +1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca +0, 28, 28, 1, 152064, 4e1c702e278fbc96775b560780411b53 +1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 +0, 29, 29, 1, 152064, 51875170b275dcf8cb2842873d1abc0d +1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 +0, 30, 30, 1, 152064, 6736c7ebe76b018e2dccc9f556d727d7 +1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 +0, 31, 31, 1, 152064, 55e737c788faaace7a743f35dd22a7b1 +1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab +0, 32, 32, 1, 152064, c32f42d61cb27de2cc635bde32b54373 +1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a +1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c +0, 33, 33, 1, 152064, 8df299932ddbd1cbe0492153bcd8bf64 +1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f +0, 34, 34, 1, 152064, 5f2991318136713262e7b6a92b59c6b0 +1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 +0, 35, 35, 1, 152064, 50165b1bbc952dd30555bebc4109acf0 +1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 +0, 36, 36, 1, 152064, 328fdca858926e5a4d76ab4a44271d80 +1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 +0, 37, 37, 1, 152064, e176eb165793b670e80d4efed7914b27 +1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 +0, 38, 38, 1, 152064, d5169722734afcfd59338fdf678061c9 +1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e +0, 39, 39, 1, 152064, 11be200f8992671b98582f8c74e3fa9c +1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d +1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 +0, 40, 40, 1, 152064, 284b53308efcdd04f6a1354587c35039 +1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 +0, 41, 41, 1, 152064, 7fd6e166b4ed2532d7f1ed6cb0d7a543 +1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb +0, 42, 42, 1, 152064, 7457fb074429971b94b481abac0ac56d +1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 +0, 43, 43, 1, 152064, 3f248b7349d32fb74b6b1693ee5bc7f5 +1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b +0, 44, 44, 1, 152064, 0ed14ef328b2f6b96610c6af5c1bea5a +1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 +0, 45, 45, 1, 152064, b17bdbf4e1a6a290e13ea7a894cb2eb5 +1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 +0, 46, 46, 1, 152064, 0168630f3f8b11a113cb29061923a043 +1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 +1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 +0, 47, 47, 1, 152064, 4c4e88381433d7b42d932b05d8a36b19 +1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 +0, 48, 48, 1, 152064, 7e1909756725d22780a3b7bd3e55f111 +1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af +0, 49, 49, 1, 152064, d66198ab70484ebc20408dee544893a8 +1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2 new file mode 100644 index 0000000000..51e55619ee --- /dev/null +++ b/tests/ref/fate/copy-shortest2 @@ -0,0 +1,124 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 47, da1ebf7f39a801230d2bcba50b3ec492 +#tb 0: 1/51200 +#media_type 0: video +#codec_id 0: mpeg4 +#dimensions 0: 352x288 +#sar 0: 1/1 +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: ac3 +#sample_rate 1: 44100 +#channel_layout 1: 4 +#channel_layout_name 1: mono +#stream#, dts, pts, duration, size, hash +1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce +0, 0, 0, 2048, 15824, 3a4cc2c2e38504cd4a336a43c8793566 +1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 +0, 2048, 2048, 2048, 13321, 1c5627081495c2b8ee9205c8db819125 +1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 +0, 4096, 4096, 2048, 11462, 7ce15c296f66af71a5d28b927bb0699e +1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade +0, 6144, 6144, 2048, 11654, 2dbe71f6e3687da4365b154499dbc08f +1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 +0, 8192, 8192, 2048, 6100, 697a62dfa0463ffa9251f88638287f3b +1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 +0, 10240, 10240, 2048, 2063, b7d9bcb7781b6c4041ae5e9f96f4d471 +1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 +1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 +0, 12288, 12288, 2048, 1585, 11b681604bda51a75c7ea521068d7c27 +1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 +0, 14336, 14336, 2048, 1475, 9fa1fced5a744fca0feffd06865c7e3a +1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 +0, 16384, 16384, 2048, 1304, f4cbd113b49fcdd7391e8a570f10c40d +1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae +0, 18432, 18432, 2048, 1390, 08ac45e537349a7572360357108701d6 +1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 +0, 20480, 20480, 2048, 1207, d5af6f80554f1d3f59da04fba9ff149c +1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 +0, 22528, 22528, 2048, 1317, 23c5b46737675b99f7857c772477ac92 +1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c +0, 24576, 24576, 2048, 9516, 20e2e4a64f11dbfb58ca4b97d8d9e6d5 +1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb +1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 +0, 26624, 26624, 2048, 858, 5cc087a6d5f7dff149f25c32d66c1a58 +1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 +0, 28672, 28672, 2048, 1146, 7b2a5417f675fddde6c3fccb5256f7de +1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 +0, 30720, 30720, 2048, 1273, fec0124dd40536b06ff5cb4f9ee57427 +1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc +0, 32768, 32768, 2048, 1342, 83fcf03894414225764fe4606e77fed9 +1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 +0, 34816, 34816, 2048, 1109, 43ccf63beb6a392f09edd8ae47639f33 +1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 +0, 36864, 36864, 2048, 1143, 9b1b76b633679afdd0c57a47fd9cb461 +1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb +0, 38912, 38912, 2048, 1221, 74e3bf875ae55dc7c756e3102889985f +1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b +1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 +0, 40960, 40960, 2048, 1193, 62366a05aa12bb99abf8428fa7859aa6 +1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d +0, 43008, 43008, 2048, 1270, 44a2d2cc9bff3b86eb74d08cfb2add7e +1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 +0, 45056, 45056, 2048, 1068, 5fc66a8b05d70e00df4e55b50144f37e +1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae +0, 47104, 47104, 2048, 1128, 74da79e4645ad9257c1db174de9e47a3 +1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed +0, 49152, 49152, 2048, 9724, 91bc413e47961f3c58b3a62b0a35a725 +1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd +0, 51200, 51200, 2048, 791, b2104ecfda6cbfef18d5510b77f44224 +1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 +1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 +0, 53248, 53248, 2048, 1008, 0ea692ed90a1ddc5a453a1294b85819a +1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 +0, 55296, 55296, 2048, 1139, 1e0ba3e2cce5b45f7496daa06f71716d +1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca +0, 57344, 57344, 2048, 1039, 7e23be81c75cebe22a9c6c08d326513b +1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 +0, 59392, 59392, 2048, 1069, 8da7d9d85333d18f29fc27396603cac8 +1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 +0, 61440, 61440, 2048, 1133, a847204db7f096e2587557bc1c093e2e +1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 +0, 63488, 63488, 2048, 988, dbea5c64e24bef364f0d7d1774bf7554 +1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab +0, 65536, 65536, 2048, 1009, 1caa3889676605f2177494bbaf3481ef +1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a +1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c +0, 67584, 67584, 2048, 1107, 43811ad7091d2b9a30644f812938f323 +1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f +0, 69632, 69632, 2048, 1191, 0dce9221ed025767c67fec5f7840af91 +1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 +0, 71680, 71680, 2048, 1147, 00270ca11c80875d4670a5b64b4aad64 +1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 +0, 73728, 73728, 2048, 8426, 3d8057fcb27ddc70720a3955571c4ac0 +1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 +0, 75776, 75776, 2048, 693, b2073d9452b98ca62d4708ea2d5a0730 +1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 +0, 77824, 77824, 2048, 890, 617e1c3312a14a9732789c4f5b9f0488 +1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e +0, 79872, 79872, 2048, 958, ba070283ceda704a7e7ee256ad75690e +1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d +1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 +0, 81920, 81920, 2048, 1036, 62c4213ff08e97cf82d1b6350f49e5e4 +1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 +0, 83968, 83968, 2048, 1021, 468fca432044d4653991ed76f7fdb161 +1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb +0, 86016, 86016, 2048, 1021, e439e670c4fd699f831d6da814f35623 +1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 +0, 88064, 88064, 2048, 1026, e4ad69687a8912a27ceb8069b567a1d0 +1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b +0, 90112, 90112, 2048, 945, 83534c6c2da202376387f86b44ad3fa8 +1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 +0, 92160, 92160, 2048, 998, b575ba085bb01752af6e15ba896f82c4 +1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 +0, 94208, 94208, 2048, 1019, 7d6ff68f2bfc7627a3a9706a8c9035b3 +1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 +1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 +0, 96256, 96256, 2048, 978, b62d6ca4a21a565071fc70c3890485f5 +1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 +0, 98304, 98304, 2048, 8690, 40627c6e6f397670bda29319b2920a6d +1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af +0, 100352, 100352, 2048, 639, 2eabe65d77af690a6e0b7209d8a51cf8 +1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/shortest b/tests/ref/fate/shortest new file mode 100644 index 0000000000..f39a730c2c --- /dev/null +++ b/tests/ref/fate/shortest @@ -0,0 +1,123 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: mpeg4 +#dimensions 0: 352x288 +#sar 0: 0/1 +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: ac3 +#sample_rate 1: 44100 +#channel_layout 1: 4 +#channel_layout_name 1: mono +#stream#, dts, pts, duration, size, hash +1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce +0, 0, 0, 1, 15854, 95fdffc627c15ec2a1764adb98378cc8, S=1, 8, 9cf0b40a4b63467e3c719c72a911acbd +1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 +0, 1, 1, 1, 13318, 61e9d6d30e533292ff37b1168e58ab11, S=1, 8, 36b12655a39dea3638d6feeaa38693f4 +1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 +0, 2, 2, 1, 11475, 5591622b2d2b557ff749fa736c631ff3, S=1, 8, 36b12655a39dea3638d6feeaa38693f4 +1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade +0, 3, 3, 1, 11629, c06ab8d81d16477f11a03c0cac2e99dd, S=1, 8, 36b12655a39dea3638d6feeaa38693f4 +1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 +0, 4, 4, 1, 6108, b2077a08d20772f03eb5a438a79e34d6, S=1, 8, 4057375d7213345ff8b5690075371608 +1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 +0, 5, 5, 1, 2073, f60858c134b710797b932f6bd67375e8, S=1, 8, c04afc86c8f48384ee20fca6c8e87238 +1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 +1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 +0, 6, 6, 1, 1593, 722a391dbe8cec12d21c24967bcd3f9a, S=1, 8, d2344c094573d1252fd75c0ba2721f0a +1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 +0, 7, 7, 1, 1465, cabebc01bc61ee73be6f5877ea7dcda9, S=1, 8, 25b6cf153f1c4424af08a91be1bea2bb +1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 +0, 8, 8, 1, 1306, e8cf3345ce9b5d482f8d766f657173d9, S=1, 8, d0b8916b10362671e64f1d73ba9d851e +1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae +0, 9, 9, 1, 1386, e8214a31192fed1d3a610aa2ea1b5ea3, S=1, 8, 56c142e2fc6ab90d85490e3bb0b21e8d +1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 +0, 10, 10, 1, 1205, b99687be797b20ff061d1226b2d4a26b, S=1, 8, c64ed668aab56d6e18d8418938acb050 +1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 +0, 11, 11, 1, 1317, ec1c7bfb91f1af72cc22ad37b600024c, S=1, 8, fb7cb9023f678ab152b0ece99ade9b59 +1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c +0, 12, 12, 1, 9546, d574659d05e5ad432928836ced7e734f, S=1, 8, 6be505c5c4671e678387ee2f3bda6994 +1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb +1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 +0, 13, 13, 1, 859, 3066311e4eeb7f69a9b20939873e2424, S=1, 8, b8160789f7975e1bc3e5dc59254dc976 +1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 +0, 14, 14, 1, 1148, e564909cefb616a28b25283c825dc815, S=1, 8, c64ed668aab56d6e18d8418938acb050 +1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 +0, 15, 15, 1, 1277, 84bccfcecef582100f222c16d610d5e8, S=1, 8, 4035ac4c4d4aadf545172fdb0202adc7 +1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc +0, 16, 16, 1, 1325, cc3efca64cb6582b2de50edb0f504f39, S=1, 8, 526bb3ebd360dd8583919f24b6379b18 +1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 +0, 17, 17, 1, 1110, 2faa567250ca713c2c49c52bbec705d2, S=1, 8, ae7b92e39e339916a550e7b0115af8ed +1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 +0, 18, 18, 1, 1150, 6c3d1e9219837fe1eca7700df25736ce, S=1, 8, e2a3142bfafcd5f23e7c1a97fdcd1611 +1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb +0, 19, 19, 1, 1209, fd6b8b2379c5cc5a05990d1bf50a2122, S=1, 8, 72021a86e6819ff2770afb3a7aba9822 +1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b +1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 +0, 20, 20, 1, 1223, d54c50d04e379f767ca0600576c42f1f, S=1, 8, 3f3be12054d7ac9a86b58534b0f85ad5 +1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d +0, 21, 21, 1, 1254, b74fd59594ea997036fb71efaaff5609, S=1, 8, 82e123514584560af379c50e566a0efd +1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 +0, 22, 22, 1, 1080, 09fdad0d2419ce79d6058c5989545231, S=1, 8, 1e919d1a427cacb065dec84067c18b2c +1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae +0, 23, 23, 1, 1096, 2ead3c39825ce9277dfb2d1588499d67, S=1, 8, dc6dbfeaaf3480bede1ca54281219d28 +1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed +0, 24, 24, 1, 9754, ac1468ede7c76fa49b0b5051dcb90c63, S=1, 8, f24545bac4cd7e6e3b37effde87556c1 +1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd +0, 25, 25, 1, 789, c77a232b086330716737047f6442e074, S=1, 8, dd599225f54a34977b143c70f35248af +1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 +1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 +0, 26, 26, 1, 1012, 24865dcc56c61c306178c451ae00b73a, S=1, 8, 431f741f44fa64eac99ceb1b820e8a04 +1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 +0, 27, 27, 1, 1138, 8fdddcd003cd2e630aa55c7f5e76da12, S=1, 8, dcec92442f44a3ecbaf807279b2b8699 +1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca +0, 28, 28, 1, 1037, 18e607adcfb97d20a072329590bda616, S=1, 8, 309a5035c7a1ea314794289ff903b511 +1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 +0, 29, 29, 1, 1070, c2d7f9699a335dd78f2c60e3ade8d2da, S=1, 8, 6da58a82c90161d200c2e5bc66901e1c +1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 +0, 30, 30, 1, 1124, d818aa7626cd6bc9707779072a459dee, S=1, 8, 958e599e4bc648be57b7c6e30cae8956 +1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 +0, 31, 31, 1, 1003, e49360236a4506e1ee35070de2cab38c, S=1, 8, e57ab3c3dd96d50ef19af0d10b633f4c +1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab +0, 32, 32, 1, 1013, 7649fc13088a882be2cb95bc57990723, S=1, 8, fd54d6fc3ca45da8e73507b3cec3bdb4 +1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a +1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c +0, 33, 33, 1, 1108, 1e7a69eb26b287579033939d186b1de0, S=1, 8, 9362b100a77fad014652eafe0eb1944d +1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f +0, 34, 34, 1, 1164, 90562532804f73e3338280d2821c8640, S=1, 8, 5c5abe1da5ff1a6a0566a7cb45b02c08 +1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 +0, 35, 35, 1, 1126, 5ea80cfb0455babf9b19446198af206b, S=1, 8, c281971cbe0832b1c13585320ff035ea +1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 +0, 36, 36, 1, 8456, c7a47c871310914cfc32663cf24166d7, S=1, 8, 3e24aaf4c9d5c084d3a3f0d90f783278 +1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 +0, 37, 37, 1, 694, 86806974f051b415bfc0996af7f47696, S=1, 8, 540ee8ae462556d0a046a736f297b173 +1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 +0, 38, 38, 1, 892, e71be76af5b6b046e44e3e6257f6bd92, S=1, 8, fc560de809ee8241e933ecd2661108b7 +1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e +0, 39, 39, 1, 1083, 505084a26ae78907fabd463e2d05bbcb, S=1, 8, 049eee0ee70335df57ac59af203fe219 +1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d +1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 +0, 40, 40, 1, 993, 0f5368f247b2cf7ecd671435aeda8b37, S=1, 8, 5550ac360fd5ed3a21840259f1a93025 +1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 +0, 41, 41, 1, 1003, aa87dcae3a211b2689284d222ed6db76, S=1, 8, 95a7c655a3d4711b01b9d5cd871d1f30 +1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb +0, 42, 42, 1, 1032, 3386f36294719e0a5186e2f2edaf0969, S=1, 8, 396a23cdb4b96b8b77886469409ad7ca +1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 +0, 43, 43, 1, 1028, 2a8be744fbdc6fe0072172c808f455c1, S=1, 8, 4fda569b89ad069d7b82b585cd6ff009 +1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b +0, 44, 44, 1, 948, cb1c1d28286d5030bd27b393653c4cc4, S=1, 8, 5b4d66a595207277db45b6ecd9b08854 +1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 +0, 45, 45, 1, 997, 2cec49ea758e4853dd5036277ae7a97c, S=1, 8, 28a85a0ee15dc8c5b5b69d882ad55a29 +1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 +0, 46, 46, 1, 978, 876c8edd1ceee6003ad9522fddec3791, S=1, 8, f2b52b616d3de191e5ae7389d57f5ab2 +1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 +1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 +0, 47, 47, 1, 988, 6d707c6f0fa6e525be40889cee04a737, S=1, 8, 720720daf8bcb72639ee2b9a3af9ce83 +1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 +0, 48, 48, 1, 8720, 5e230de451b13a8fbfd0432da23ab6b3, S=1, 8, 997caa31a1cdf2d03b5d243cd0755949 +1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af +0, 49, 49, 1, 635, 16962fc4bae92dda139fb107d78b8073, S=1, 8, f9e79a0c8a7a7796e9adf5f4f3c48102 +1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d From 686c7c132d82c47446cbecc2d0096f33bfb09ca4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 1 Dec 2021 20:30:06 -0300 Subject: [PATCH 326/894] fate/ffmpeg: add missing bitexact flags to the shortest tests Should fix fate failures on some targets. Signed-off-by: James Almer --- tests/fate/ffmpeg.mak | 15 ++--- tests/ref/fate/copy-shortest1 | 107 +++++++++++++++++----------------- tests/ref/fate/copy-shortest2 | 92 ++++++++++++++--------------- 3 files changed, 108 insertions(+), 106 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index b43db423a9..279cb140ac 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -88,7 +88,7 @@ fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ FATE_FFMPEG-$(call ALLYES, SINE_FILTER AMIX_FILTER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-shortest fate-shortest: tests/data/vsynth_lena.yuv -fate-shortest: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -c:v mpeg4 -c:a ac3_fixed -shortest +fate-shortest: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -c:v mpeg4 -c:a ac3_fixed -shortest FATE_STREAMCOPY-$(call ALLYES, EAC3_DEMUXER MOV_MUXER) += fate-copy-trac3074 fate-copy-trac3074: $(SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 @@ -134,18 +134,19 @@ FATE_STREAMCOPY-$(CONFIG_FLV_DEMUXER) += fate-ffmpeg-streamloop fate-ffmpeg-streamloop: $(SAMPLES)/flv/streamloop.flv fate-ffmpeg-streamloop: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/streamloop.flv -c copy -FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER AC3_FIXED_ENCODER) += fate-copy-shortest1 -fate-copy-shortest1: tests/data/vsynth_lena.yuv -fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest - tests/data/audio_shorter_than_video.nut: TAG = GEN tests/data/audio_shorter_than_video.nut: tests/data/vsynth_lena.yuv tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ - -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -c:v mpeg4 \ - -f lavfi -i "sine=1000:d=1" -c:a pcm_s16le \ + -sws_flags +accurate_rnd+bitexact -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ + -f lavfi -i "sine=1000:d=1" \ + -sws_flags +accurate_rnd+bitexact -c:v mpeg4 -c:a pcm_s16le -bitexact \ -y $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut 2>/dev/null +FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest1 +fate-copy-shortest1: tests/data/audio_shorter_than_video.nut +fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest + FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest2 fate-copy-shortest2: tests/data/audio_shorter_than_video.nut fate-copy-shortest2: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 1:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1 index c4d4a0c0f9..ae7d912b08 100644 --- a/tests/ref/fate/copy-shortest1 +++ b/tests/ref/fate/copy-shortest1 @@ -1,11 +1,12 @@ #format: frame checksums #version: 2 #hash: MD5 -#tb 0: 1/25 +#extradata 0, 30, 226f0a640065a7bbc3a3e6dd5067de5a +#tb 0: 1/51200 #media_type 0: video -#codec_id 0: rawvideo +#codec_id 0: mpeg4 #dimensions 0: 352x288 -#sar 0: 0/1 +#sar 0: 1/1 #tb 1: 1/44100 #media_type 1: audio #codec_id 1: ac3 @@ -14,110 +15,110 @@ #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 1, 152064, 64ffa0d5a62ddf325a92195fda238dd4 +0, 0, 0, 2048, 15824, 3a4cc2c2e38504cd4a336a43c8793566 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 1, 1, 1, 152064, d17acf3ef7ce8c8d0ac1c3b89d77d6dc +0, 2048, 2048, 2048, 13318, 61e9d6d30e533292ff37b1168e58ab11 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 2, 2, 1, 152064, c08a06d8a267f8fb94e64362f8d5f311 +0, 4096, 4096, 2048, 11475, 5591622b2d2b557ff749fa736c631ff3 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 3, 3, 1, 152064, 029eea5860e7b326dd7e10e2be64a098 +0, 6144, 6144, 2048, 11629, c06ab8d81d16477f11a03c0cac2e99dd 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 4, 4, 1, 152064, aabca39f06e9b19f84560db8a43de0cf +0, 8192, 8192, 2048, 6108, b2077a08d20772f03eb5a438a79e34d6 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 5, 5, 1, 152064, 6681a5e5af601bbf0e0318d1f240a955 +0, 10240, 10240, 2048, 2073, f60858c134b710797b932f6bd67375e8 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 6, 6, 1, 152064, 35f466e17c2b3a9de281a0405dd9bc5c +0, 12288, 12288, 2048, 1593, 722a391dbe8cec12d21c24967bcd3f9a 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 7, 7, 1, 152064, a6af204b9a1a091f5b2e8981a73df3aa +0, 14336, 14336, 2048, 1465, cabebc01bc61ee73be6f5877ea7dcda9 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 8, 8, 1, 152064, c037c758227f61da1faffb149af750a5 +0, 16384, 16384, 2048, 1306, e8cf3345ce9b5d482f8d766f657173d9 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 9, 9, 1, 152064, 76d1d9e8374070db553c9a89482dc165 +0, 18432, 18432, 2048, 1386, e8214a31192fed1d3a610aa2ea1b5ea3 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 10, 10, 1, 152064, 9361f2dac0279cb019948694daeff0b1 +0, 20480, 20480, 2048, 1205, b99687be797b20ff061d1226b2d4a26b 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 11, 11, 1, 152064, 97a544d9c6b8f50afd15fe6dfd4c22a2 +0, 22528, 22528, 2048, 1317, ec1c7bfb91f1af72cc22ad37b600024c 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 12, 12, 1, 152064, dec68cf40dcf205f739b909d178310cf +0, 24576, 24576, 2048, 9516, 20e2e4a64f11dbfb58ca4b97d8d9e6d5 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 13, 13, 1, 152064, 6afd4a8feb3f8fc1825d0da292013472 +0, 26624, 26624, 2048, 859, 3066311e4eeb7f69a9b20939873e2424 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 14, 14, 1, 152064, d7297857fbfcf3fe0157eafe4114f957 +0, 28672, 28672, 2048, 1148, e564909cefb616a28b25283c825dc815 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 15, 15, 1, 152064, 3e004f5a07599daec056189f8ab879e6 +0, 30720, 30720, 2048, 1277, 84bccfcecef582100f222c16d610d5e8 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 16, 16, 1, 152064, fb8dfc19d47a925f6bbcb8a334a80f2b +0, 32768, 32768, 2048, 1325, cc3efca64cb6582b2de50edb0f504f39 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 17, 17, 1, 152064, 8aad1267917e26696593b35aabeaae60 +0, 34816, 34816, 2048, 1110, 2faa567250ca713c2c49c52bbec705d2 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 18, 18, 1, 152064, dce70f7213f70a248c1ffd78244a0757 +0, 36864, 36864, 2048, 1150, 6c3d1e9219837fe1eca7700df25736ce 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 19, 19, 1, 152064, fbe3fa678d3b8d48f1d7fd45cb869241 +0, 38912, 38912, 2048, 1209, fd6b8b2379c5cc5a05990d1bf50a2122 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 20, 20, 1, 152064, eef85510c95abc810269888dd5037e38 +0, 40960, 40960, 2048, 1223, d54c50d04e379f767ca0600576c42f1f 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 21, 21, 1, 152064, 30ccae29a495eb6157930a3db50ad171 +0, 43008, 43008, 2048, 1254, b74fd59594ea997036fb71efaaff5609 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 22, 22, 1, 152064, 5cf0001156e38570b830509ec727f956 +0, 45056, 45056, 2048, 1080, 09fdad0d2419ce79d6058c5989545231 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 23, 23, 1, 152064, 6686944299e7aea38756b8321a5ad5fd +0, 47104, 47104, 2048, 1096, 2ead3c39825ce9277dfb2d1588499d67 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 24, 24, 1, 152064, e618b079c3083cc4f4b080b6c6b8f645 +0, 49152, 49152, 2048, 9724, 91bc413e47961f3c58b3a62b0a35a725 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 25, 25, 1, 152064, ebf84cc4a497cc56d39e10bed3c0418e +0, 51200, 51200, 2048, 789, c77a232b086330716737047f6442e074 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 26, 26, 1, 152064, 10ee72dac1749c7b68f8a9318270953a +0, 53248, 53248, 2048, 1012, 24865dcc56c61c306178c451ae00b73a 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 27, 27, 1, 152064, 32e3028c0bf5e27d86972a51ce33927c +0, 55296, 55296, 2048, 1138, 8fdddcd003cd2e630aa55c7f5e76da12 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 28, 28, 1, 152064, 4e1c702e278fbc96775b560780411b53 +0, 57344, 57344, 2048, 1037, 18e607adcfb97d20a072329590bda616 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 29, 29, 1, 152064, 51875170b275dcf8cb2842873d1abc0d +0, 59392, 59392, 2048, 1070, c2d7f9699a335dd78f2c60e3ade8d2da 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 30, 30, 1, 152064, 6736c7ebe76b018e2dccc9f556d727d7 +0, 61440, 61440, 2048, 1124, d818aa7626cd6bc9707779072a459dee 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 31, 31, 1, 152064, 55e737c788faaace7a743f35dd22a7b1 +0, 63488, 63488, 2048, 1003, e49360236a4506e1ee35070de2cab38c 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 32, 32, 1, 152064, c32f42d61cb27de2cc635bde32b54373 +0, 65536, 65536, 2048, 1013, 7649fc13088a882be2cb95bc57990723 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 33, 33, 1, 152064, 8df299932ddbd1cbe0492153bcd8bf64 +0, 67584, 67584, 2048, 1108, 1e7a69eb26b287579033939d186b1de0 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 34, 34, 1, 152064, 5f2991318136713262e7b6a92b59c6b0 +0, 69632, 69632, 2048, 1164, 90562532804f73e3338280d2821c8640 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 35, 35, 1, 152064, 50165b1bbc952dd30555bebc4109acf0 +0, 71680, 71680, 2048, 1126, 5ea80cfb0455babf9b19446198af206b 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 36, 36, 1, 152064, 328fdca858926e5a4d76ab4a44271d80 +0, 73728, 73728, 2048, 8426, 3d8057fcb27ddc70720a3955571c4ac0 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 37, 37, 1, 152064, e176eb165793b670e80d4efed7914b27 +0, 75776, 75776, 2048, 694, 86806974f051b415bfc0996af7f47696 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 38, 38, 1, 152064, d5169722734afcfd59338fdf678061c9 +0, 77824, 77824, 2048, 892, e71be76af5b6b046e44e3e6257f6bd92 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 39, 39, 1, 152064, 11be200f8992671b98582f8c74e3fa9c +0, 79872, 79872, 2048, 1083, 505084a26ae78907fabd463e2d05bbcb 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 40, 40, 1, 152064, 284b53308efcdd04f6a1354587c35039 +0, 81920, 81920, 2048, 993, 0f5368f247b2cf7ecd671435aeda8b37 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 41, 41, 1, 152064, 7fd6e166b4ed2532d7f1ed6cb0d7a543 +0, 83968, 83968, 2048, 1003, aa87dcae3a211b2689284d222ed6db76 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 42, 42, 1, 152064, 7457fb074429971b94b481abac0ac56d +0, 86016, 86016, 2048, 1032, 3386f36294719e0a5186e2f2edaf0969 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 43, 43, 1, 152064, 3f248b7349d32fb74b6b1693ee5bc7f5 +0, 88064, 88064, 2048, 1028, 2a8be744fbdc6fe0072172c808f455c1 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 44, 44, 1, 152064, 0ed14ef328b2f6b96610c6af5c1bea5a +0, 90112, 90112, 2048, 948, cb1c1d28286d5030bd27b393653c4cc4 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 45, 45, 1, 152064, b17bdbf4e1a6a290e13ea7a894cb2eb5 +0, 92160, 92160, 2048, 997, 2cec49ea758e4853dd5036277ae7a97c 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 46, 46, 1, 152064, 0168630f3f8b11a113cb29061923a043 +0, 94208, 94208, 2048, 978, 876c8edd1ceee6003ad9522fddec3791 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 47, 47, 1, 152064, 4c4e88381433d7b42d932b05d8a36b19 +0, 96256, 96256, 2048, 988, 6d707c6f0fa6e525be40889cee04a737 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 48, 48, 1, 152064, 7e1909756725d22780a3b7bd3e55f111 +0, 98304, 98304, 2048, 8690, 40627c6e6f397670bda29319b2920a6d 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 49, 49, 1, 152064, d66198ab70484ebc20408dee544893a8 +0, 100352, 100352, 2048, 635, 16962fc4bae92dda139fb107d78b8073 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2 index 51e55619ee..ae7d912b08 100644 --- a/tests/ref/fate/copy-shortest2 +++ b/tests/ref/fate/copy-shortest2 @@ -1,7 +1,7 @@ #format: frame checksums #version: 2 #hash: MD5 -#extradata 0, 47, da1ebf7f39a801230d2bcba50b3ec492 +#extradata 0, 30, 226f0a640065a7bbc3a3e6dd5067de5a #tb 0: 1/51200 #media_type 0: video #codec_id 0: mpeg4 @@ -17,108 +17,108 @@ 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce 0, 0, 0, 2048, 15824, 3a4cc2c2e38504cd4a336a43c8793566 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 2048, 2048, 2048, 13321, 1c5627081495c2b8ee9205c8db819125 +0, 2048, 2048, 2048, 13318, 61e9d6d30e533292ff37b1168e58ab11 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 4096, 4096, 2048, 11462, 7ce15c296f66af71a5d28b927bb0699e +0, 4096, 4096, 2048, 11475, 5591622b2d2b557ff749fa736c631ff3 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 6144, 6144, 2048, 11654, 2dbe71f6e3687da4365b154499dbc08f +0, 6144, 6144, 2048, 11629, c06ab8d81d16477f11a03c0cac2e99dd 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 8192, 8192, 2048, 6100, 697a62dfa0463ffa9251f88638287f3b +0, 8192, 8192, 2048, 6108, b2077a08d20772f03eb5a438a79e34d6 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 10240, 10240, 2048, 2063, b7d9bcb7781b6c4041ae5e9f96f4d471 +0, 10240, 10240, 2048, 2073, f60858c134b710797b932f6bd67375e8 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 12288, 12288, 2048, 1585, 11b681604bda51a75c7ea521068d7c27 +0, 12288, 12288, 2048, 1593, 722a391dbe8cec12d21c24967bcd3f9a 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 14336, 14336, 2048, 1475, 9fa1fced5a744fca0feffd06865c7e3a +0, 14336, 14336, 2048, 1465, cabebc01bc61ee73be6f5877ea7dcda9 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 16384, 16384, 2048, 1304, f4cbd113b49fcdd7391e8a570f10c40d +0, 16384, 16384, 2048, 1306, e8cf3345ce9b5d482f8d766f657173d9 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 18432, 18432, 2048, 1390, 08ac45e537349a7572360357108701d6 +0, 18432, 18432, 2048, 1386, e8214a31192fed1d3a610aa2ea1b5ea3 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 20480, 20480, 2048, 1207, d5af6f80554f1d3f59da04fba9ff149c +0, 20480, 20480, 2048, 1205, b99687be797b20ff061d1226b2d4a26b 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 22528, 22528, 2048, 1317, 23c5b46737675b99f7857c772477ac92 +0, 22528, 22528, 2048, 1317, ec1c7bfb91f1af72cc22ad37b600024c 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c 0, 24576, 24576, 2048, 9516, 20e2e4a64f11dbfb58ca4b97d8d9e6d5 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 26624, 26624, 2048, 858, 5cc087a6d5f7dff149f25c32d66c1a58 +0, 26624, 26624, 2048, 859, 3066311e4eeb7f69a9b20939873e2424 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 28672, 28672, 2048, 1146, 7b2a5417f675fddde6c3fccb5256f7de +0, 28672, 28672, 2048, 1148, e564909cefb616a28b25283c825dc815 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 30720, 30720, 2048, 1273, fec0124dd40536b06ff5cb4f9ee57427 +0, 30720, 30720, 2048, 1277, 84bccfcecef582100f222c16d610d5e8 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 32768, 32768, 2048, 1342, 83fcf03894414225764fe4606e77fed9 +0, 32768, 32768, 2048, 1325, cc3efca64cb6582b2de50edb0f504f39 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 34816, 34816, 2048, 1109, 43ccf63beb6a392f09edd8ae47639f33 +0, 34816, 34816, 2048, 1110, 2faa567250ca713c2c49c52bbec705d2 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 36864, 36864, 2048, 1143, 9b1b76b633679afdd0c57a47fd9cb461 +0, 36864, 36864, 2048, 1150, 6c3d1e9219837fe1eca7700df25736ce 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 38912, 38912, 2048, 1221, 74e3bf875ae55dc7c756e3102889985f +0, 38912, 38912, 2048, 1209, fd6b8b2379c5cc5a05990d1bf50a2122 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 40960, 40960, 2048, 1193, 62366a05aa12bb99abf8428fa7859aa6 +0, 40960, 40960, 2048, 1223, d54c50d04e379f767ca0600576c42f1f 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 43008, 43008, 2048, 1270, 44a2d2cc9bff3b86eb74d08cfb2add7e +0, 43008, 43008, 2048, 1254, b74fd59594ea997036fb71efaaff5609 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 45056, 45056, 2048, 1068, 5fc66a8b05d70e00df4e55b50144f37e +0, 45056, 45056, 2048, 1080, 09fdad0d2419ce79d6058c5989545231 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 47104, 47104, 2048, 1128, 74da79e4645ad9257c1db174de9e47a3 +0, 47104, 47104, 2048, 1096, 2ead3c39825ce9277dfb2d1588499d67 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed 0, 49152, 49152, 2048, 9724, 91bc413e47961f3c58b3a62b0a35a725 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 51200, 51200, 2048, 791, b2104ecfda6cbfef18d5510b77f44224 +0, 51200, 51200, 2048, 789, c77a232b086330716737047f6442e074 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 53248, 53248, 2048, 1008, 0ea692ed90a1ddc5a453a1294b85819a +0, 53248, 53248, 2048, 1012, 24865dcc56c61c306178c451ae00b73a 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 55296, 55296, 2048, 1139, 1e0ba3e2cce5b45f7496daa06f71716d +0, 55296, 55296, 2048, 1138, 8fdddcd003cd2e630aa55c7f5e76da12 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 57344, 57344, 2048, 1039, 7e23be81c75cebe22a9c6c08d326513b +0, 57344, 57344, 2048, 1037, 18e607adcfb97d20a072329590bda616 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 59392, 59392, 2048, 1069, 8da7d9d85333d18f29fc27396603cac8 +0, 59392, 59392, 2048, 1070, c2d7f9699a335dd78f2c60e3ade8d2da 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 61440, 61440, 2048, 1133, a847204db7f096e2587557bc1c093e2e +0, 61440, 61440, 2048, 1124, d818aa7626cd6bc9707779072a459dee 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 63488, 63488, 2048, 988, dbea5c64e24bef364f0d7d1774bf7554 +0, 63488, 63488, 2048, 1003, e49360236a4506e1ee35070de2cab38c 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 65536, 65536, 2048, 1009, 1caa3889676605f2177494bbaf3481ef +0, 65536, 65536, 2048, 1013, 7649fc13088a882be2cb95bc57990723 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 67584, 67584, 2048, 1107, 43811ad7091d2b9a30644f812938f323 +0, 67584, 67584, 2048, 1108, 1e7a69eb26b287579033939d186b1de0 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 69632, 69632, 2048, 1191, 0dce9221ed025767c67fec5f7840af91 +0, 69632, 69632, 2048, 1164, 90562532804f73e3338280d2821c8640 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 71680, 71680, 2048, 1147, 00270ca11c80875d4670a5b64b4aad64 +0, 71680, 71680, 2048, 1126, 5ea80cfb0455babf9b19446198af206b 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 0, 73728, 73728, 2048, 8426, 3d8057fcb27ddc70720a3955571c4ac0 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 75776, 75776, 2048, 693, b2073d9452b98ca62d4708ea2d5a0730 +0, 75776, 75776, 2048, 694, 86806974f051b415bfc0996af7f47696 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 77824, 77824, 2048, 890, 617e1c3312a14a9732789c4f5b9f0488 +0, 77824, 77824, 2048, 892, e71be76af5b6b046e44e3e6257f6bd92 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 79872, 79872, 2048, 958, ba070283ceda704a7e7ee256ad75690e +0, 79872, 79872, 2048, 1083, 505084a26ae78907fabd463e2d05bbcb 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 81920, 81920, 2048, 1036, 62c4213ff08e97cf82d1b6350f49e5e4 +0, 81920, 81920, 2048, 993, 0f5368f247b2cf7ecd671435aeda8b37 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 83968, 83968, 2048, 1021, 468fca432044d4653991ed76f7fdb161 +0, 83968, 83968, 2048, 1003, aa87dcae3a211b2689284d222ed6db76 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 86016, 86016, 2048, 1021, e439e670c4fd699f831d6da814f35623 +0, 86016, 86016, 2048, 1032, 3386f36294719e0a5186e2f2edaf0969 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 88064, 88064, 2048, 1026, e4ad69687a8912a27ceb8069b567a1d0 +0, 88064, 88064, 2048, 1028, 2a8be744fbdc6fe0072172c808f455c1 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 90112, 90112, 2048, 945, 83534c6c2da202376387f86b44ad3fa8 +0, 90112, 90112, 2048, 948, cb1c1d28286d5030bd27b393653c4cc4 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 92160, 92160, 2048, 998, b575ba085bb01752af6e15ba896f82c4 +0, 92160, 92160, 2048, 997, 2cec49ea758e4853dd5036277ae7a97c 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 94208, 94208, 2048, 1019, 7d6ff68f2bfc7627a3a9706a8c9035b3 +0, 94208, 94208, 2048, 978, 876c8edd1ceee6003ad9522fddec3791 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 96256, 96256, 2048, 978, b62d6ca4a21a565071fc70c3890485f5 +0, 96256, 96256, 2048, 988, 6d707c6f0fa6e525be40889cee04a737 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 0, 98304, 98304, 2048, 8690, 40627c6e6f397670bda29319b2920a6d 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 100352, 100352, 2048, 639, 2eabe65d77af690a6e0b7209d8a51cf8 +0, 100352, 100352, 2048, 635, 16962fc4bae92dda139fb107d78b8073 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d From 6507e96e71b90a299677eca352ea253700dee2a2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 1 Dec 2021 22:02:45 -0300 Subject: [PATCH 327/894] fate/ffmpeg: add some more flags to the shortest tests Signed-off-by: James Almer --- tests/fate/ffmpeg.mak | 10 ++-- tests/ref/fate/copy-shortest1 | 100 +++++++++++++++++----------------- tests/ref/fate/copy-shortest2 | 100 +++++++++++++++++----------------- tests/ref/fate/shortest | 100 +++++++++++++++++----------------- 4 files changed, 155 insertions(+), 155 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 279cb140ac..8190eb974a 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -88,7 +88,7 @@ fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ FATE_FFMPEG-$(call ALLYES, SINE_FILTER AMIX_FILTER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-shortest fate-shortest: tests/data/vsynth_lena.yuv -fate-shortest: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -c:v mpeg4 -c:a ac3_fixed -shortest +fate-shortest: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -c:a ac3_fixed -shortest FATE_STREAMCOPY-$(call ALLYES, EAC3_DEMUXER MOV_MUXER) += fate-copy-trac3074 fate-copy-trac3074: $(SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 @@ -138,18 +138,18 @@ tests/data/audio_shorter_than_video.nut: TAG = GEN tests/data/audio_shorter_than_video.nut: tests/data/vsynth_lena.yuv tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ - -sws_flags +accurate_rnd+bitexact -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ + -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ -f lavfi -i "sine=1000:d=1" \ - -sws_flags +accurate_rnd+bitexact -c:v mpeg4 -c:a pcm_s16le -bitexact \ + -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -c:a pcm_s16le -bitexact \ -y $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut 2>/dev/null FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest1 fate-copy-shortest1: tests/data/audio_shorter_than_video.nut -fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest +fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -fflags +bitexact -flags +bitexact -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -fflags +bitexact -flags +bitexact -c:v copy -c:a ac3_fixed -shortest FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest2 fate-copy-shortest2: tests/data/audio_shorter_than_video.nut -fate-copy-shortest2: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 1:v:0 -map "[audio]" -c:v copy -c:a ac3_fixed -shortest +fate-copy-shortest2: CMD = framemd5 -auto_conversion_filters -fflags +bitexact -flags +bitexact -f lavfi -i "sine=3000:d=10" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 1:v:0 -map "[audio]" -fflags +bitexact -flags +bitexact -c:v copy -c:a ac3_fixed -shortest fate-streamcopy: $(FATE_STREAMCOPY-yes) diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1 index ae7d912b08..6f5593fc15 100644 --- a/tests/ref/fate/copy-shortest1 +++ b/tests/ref/fate/copy-shortest1 @@ -15,110 +15,110 @@ #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 2048, 15824, 3a4cc2c2e38504cd4a336a43c8793566 +0, 0, 0, 2048, 8876, b18b95893443cf5840d5962ad3456e97 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 2048, 2048, 2048, 13318, 61e9d6d30e533292ff37b1168e58ab11 +0, 2048, 2048, 2048, 1025, 3c8f2dba6d80ebd4f656ecb772d46c9d 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 4096, 4096, 2048, 11475, 5591622b2d2b557ff749fa736c631ff3 +0, 4096, 4096, 2048, 1226, 03470d542c38b78c48df45f19f2958e7 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 6144, 6144, 2048, 11629, c06ab8d81d16477f11a03c0cac2e99dd +0, 6144, 6144, 2048, 1353, 51f123ef389e7ccb20d382ce779d81ed 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 8192, 8192, 2048, 6108, b2077a08d20772f03eb5a438a79e34d6 +0, 8192, 8192, 2048, 1421, 19897f392cc3517485bc6acfed2c2e2f 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 10240, 10240, 2048, 2073, f60858c134b710797b932f6bd67375e8 +0, 10240, 10240, 2048, 1446, 6d5a5dc31d09c144fba37c4e569f6e35 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 12288, 12288, 2048, 1593, 722a391dbe8cec12d21c24967bcd3f9a +0, 12288, 12288, 2048, 1483, 299f60d66033bab84ee737c6056e8588 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 14336, 14336, 2048, 1465, cabebc01bc61ee73be6f5877ea7dcda9 +0, 14336, 14336, 2048, 1494, 54759f501f33744e81a456b5e4d695f7 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 16384, 16384, 2048, 1306, e8cf3345ce9b5d482f8d766f657173d9 +0, 16384, 16384, 2048, 1552, 446661f8d2ee9b82c868cffb26160054 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 18432, 18432, 2048, 1386, e8214a31192fed1d3a610aa2ea1b5ea3 +0, 18432, 18432, 2048, 1521, 0db5cd946c19b1552eacf56901558e5c 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 20480, 20480, 2048, 1205, b99687be797b20ff061d1226b2d4a26b +0, 20480, 20480, 2048, 1545, 725ac20d7c171e448dce01d660021118 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 22528, 22528, 2048, 1317, ec1c7bfb91f1af72cc22ad37b600024c +0, 22528, 22528, 2048, 1556, 429e63d26b4b3b95b91547489e49293d 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 24576, 24576, 2048, 9516, 20e2e4a64f11dbfb58ca4b97d8d9e6d5 +0, 24576, 24576, 2048, 8659, fdf5109e322c9e5b80d9453a6ca4853d 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 26624, 26624, 2048, 859, 3066311e4eeb7f69a9b20939873e2424 +0, 26624, 26624, 2048, 1144, 74ee1db0568ccf0c866189e59c8530cc 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 28672, 28672, 2048, 1148, e564909cefb616a28b25283c825dc815 +0, 28672, 28672, 2048, 1404, 9ddf9ceb0f25e54813f340c52b78a21f 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 30720, 30720, 2048, 1277, 84bccfcecef582100f222c16d610d5e8 +0, 30720, 30720, 2048, 1550, 52ca630df0df5d29a3d4d0133e746d39 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 32768, 32768, 2048, 1325, cc3efca64cb6582b2de50edb0f504f39 +0, 32768, 32768, 2048, 1549, d999030e465c63639d2c501180ef9f63 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 34816, 34816, 2048, 1110, 2faa567250ca713c2c49c52bbec705d2 +0, 34816, 34816, 2048, 1582, 2ea6009ba8964412d0be2286296eb255 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 36864, 36864, 2048, 1150, 6c3d1e9219837fe1eca7700df25736ce +0, 36864, 36864, 2048, 1519, ba2c386a35843ce0bb25b4f5c17e2ee6 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 38912, 38912, 2048, 1209, fd6b8b2379c5cc5a05990d1bf50a2122 +0, 38912, 38912, 2048, 1541, 34e3b4b5eb4ac0a0ab1fee2df6c38007 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 40960, 40960, 2048, 1223, d54c50d04e379f767ca0600576c42f1f +0, 40960, 40960, 2048, 1578, f7c6d15a0de6088a1547d4be0898387f 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 43008, 43008, 2048, 1254, b74fd59594ea997036fb71efaaff5609 +0, 43008, 43008, 2048, 1622, e568e8b1bf951006f7d025890b950e5d 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 45056, 45056, 2048, 1080, 09fdad0d2419ce79d6058c5989545231 +0, 45056, 45056, 2048, 1611, a208ef59b6f176a78d6c9113df17cf3d 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 47104, 47104, 2048, 1096, 2ead3c39825ce9277dfb2d1588499d67 +0, 47104, 47104, 2048, 1706, f298b1930c927839470258f50d456dc8 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 49152, 49152, 2048, 9724, 91bc413e47961f3c58b3a62b0a35a725 +0, 49152, 49152, 2048, 9737, 94e0e1fa27e7e57a956e0fc27670e5c8 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 51200, 51200, 2048, 789, c77a232b086330716737047f6442e074 +0, 51200, 51200, 2048, 1323, 248d92526f1e6a0d5e7592b40ac213c0 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 53248, 53248, 2048, 1012, 24865dcc56c61c306178c451ae00b73a +0, 53248, 53248, 2048, 1621, 1ee6a5eb09be8ab281d05125c2868c56 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 55296, 55296, 2048, 1138, 8fdddcd003cd2e630aa55c7f5e76da12 +0, 55296, 55296, 2048, 1698, db8b8ca03eca285d02dbce6eaaacdfd1 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 57344, 57344, 2048, 1037, 18e607adcfb97d20a072329590bda616 +0, 57344, 57344, 2048, 1793, c50e4bdacb3ecef9c94be7b292929018 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 59392, 59392, 2048, 1070, c2d7f9699a335dd78f2c60e3ade8d2da +0, 59392, 59392, 2048, 1805, 1db64693c5ca5595b2f47097ffdfc612 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 61440, 61440, 2048, 1124, d818aa7626cd6bc9707779072a459dee +0, 61440, 61440, 2048, 1880, 9f96e1bc1f3b595d6cd626dced55416f 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 63488, 63488, 2048, 1003, e49360236a4506e1ee35070de2cab38c +0, 63488, 63488, 2048, 1902, 209393253d103d83d8dddde7fe044953 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 65536, 65536, 2048, 1013, 7649fc13088a882be2cb95bc57990723 +0, 65536, 65536, 2048, 1896, 9a845e06daafc1dd83d77fe507569968 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 67584, 67584, 2048, 1108, 1e7a69eb26b287579033939d186b1de0 +0, 67584, 67584, 2048, 1954, 77c37124c545198b688518508299f5f8 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 69632, 69632, 2048, 1164, 90562532804f73e3338280d2821c8640 +0, 69632, 69632, 2048, 1989, 0b142544ef59e421e33a40f9e685dffa 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 71680, 71680, 2048, 1126, 5ea80cfb0455babf9b19446198af206b +0, 71680, 71680, 2048, 2042, f69d73e0af0b4d9ef65205d8a0ee0937 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 73728, 73728, 2048, 8426, 3d8057fcb27ddc70720a3955571c4ac0 +0, 73728, 73728, 2048, 10838, bd02df61e3f5c0aa572904220aaf04a6 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 75776, 75776, 2048, 694, 86806974f051b415bfc0996af7f47696 +0, 75776, 75776, 2048, 1511, 6ab5a58771e346bd8756fdd68139ad8e 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 77824, 77824, 2048, 892, e71be76af5b6b046e44e3e6257f6bd92 +0, 77824, 77824, 2048, 1780, 62e0bc487aa55ad381d0a1e7f8b7a477 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 79872, 79872, 2048, 1083, 505084a26ae78907fabd463e2d05bbcb +0, 79872, 79872, 2048, 1953, ad1854098648e499e347cf828202d1d5 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 81920, 81920, 2048, 993, 0f5368f247b2cf7ecd671435aeda8b37 +0, 81920, 81920, 2048, 2036, da8405d19586da34274a578f4972fd7f 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 83968, 83968, 2048, 1003, aa87dcae3a211b2689284d222ed6db76 +0, 83968, 83968, 2048, 1980, e046fca4a3652fad1b0b22e49a290dd8 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 86016, 86016, 2048, 1032, 3386f36294719e0a5186e2f2edaf0969 +0, 86016, 86016, 2048, 2014, 01806ec06d4cdb2b840a6f7993b648e3 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 88064, 88064, 2048, 1028, 2a8be744fbdc6fe0072172c808f455c1 +0, 88064, 88064, 2048, 2040, 19c5cc70489711d467ef7ef4414fdf6a 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 90112, 90112, 2048, 948, cb1c1d28286d5030bd27b393653c4cc4 +0, 90112, 90112, 2048, 2071, 2bc9f2d22ac276366337341e89efd6cb 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 92160, 92160, 2048, 997, 2cec49ea758e4853dd5036277ae7a97c +0, 92160, 92160, 2048, 2117, 7173333f3ff643752b8afea6d5486117 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 94208, 94208, 2048, 978, 876c8edd1ceee6003ad9522fddec3791 +0, 94208, 94208, 2048, 2169, fda9c958dc9fea54efa935624528a902 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 96256, 96256, 2048, 988, 6d707c6f0fa6e525be40889cee04a737 +0, 96256, 96256, 2048, 2096, 9516005a46f05f1a582524be91c4d672 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 98304, 98304, 2048, 8690, 40627c6e6f397670bda29319b2920a6d +0, 98304, 98304, 2048, 11219, 834f992165c0ee5e5a60fff78610b449 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 100352, 100352, 2048, 635, 16962fc4bae92dda139fb107d78b8073 +0, 100352, 100352, 2048, 1506, 74f01869f22e72e244f31e2da2614676 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2 index ae7d912b08..6f5593fc15 100644 --- a/tests/ref/fate/copy-shortest2 +++ b/tests/ref/fate/copy-shortest2 @@ -15,110 +15,110 @@ #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 2048, 15824, 3a4cc2c2e38504cd4a336a43c8793566 +0, 0, 0, 2048, 8876, b18b95893443cf5840d5962ad3456e97 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 2048, 2048, 2048, 13318, 61e9d6d30e533292ff37b1168e58ab11 +0, 2048, 2048, 2048, 1025, 3c8f2dba6d80ebd4f656ecb772d46c9d 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 4096, 4096, 2048, 11475, 5591622b2d2b557ff749fa736c631ff3 +0, 4096, 4096, 2048, 1226, 03470d542c38b78c48df45f19f2958e7 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 6144, 6144, 2048, 11629, c06ab8d81d16477f11a03c0cac2e99dd +0, 6144, 6144, 2048, 1353, 51f123ef389e7ccb20d382ce779d81ed 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 8192, 8192, 2048, 6108, b2077a08d20772f03eb5a438a79e34d6 +0, 8192, 8192, 2048, 1421, 19897f392cc3517485bc6acfed2c2e2f 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 10240, 10240, 2048, 2073, f60858c134b710797b932f6bd67375e8 +0, 10240, 10240, 2048, 1446, 6d5a5dc31d09c144fba37c4e569f6e35 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 12288, 12288, 2048, 1593, 722a391dbe8cec12d21c24967bcd3f9a +0, 12288, 12288, 2048, 1483, 299f60d66033bab84ee737c6056e8588 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 14336, 14336, 2048, 1465, cabebc01bc61ee73be6f5877ea7dcda9 +0, 14336, 14336, 2048, 1494, 54759f501f33744e81a456b5e4d695f7 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 16384, 16384, 2048, 1306, e8cf3345ce9b5d482f8d766f657173d9 +0, 16384, 16384, 2048, 1552, 446661f8d2ee9b82c868cffb26160054 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 18432, 18432, 2048, 1386, e8214a31192fed1d3a610aa2ea1b5ea3 +0, 18432, 18432, 2048, 1521, 0db5cd946c19b1552eacf56901558e5c 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 20480, 20480, 2048, 1205, b99687be797b20ff061d1226b2d4a26b +0, 20480, 20480, 2048, 1545, 725ac20d7c171e448dce01d660021118 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 22528, 22528, 2048, 1317, ec1c7bfb91f1af72cc22ad37b600024c +0, 22528, 22528, 2048, 1556, 429e63d26b4b3b95b91547489e49293d 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 24576, 24576, 2048, 9516, 20e2e4a64f11dbfb58ca4b97d8d9e6d5 +0, 24576, 24576, 2048, 8659, fdf5109e322c9e5b80d9453a6ca4853d 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 26624, 26624, 2048, 859, 3066311e4eeb7f69a9b20939873e2424 +0, 26624, 26624, 2048, 1144, 74ee1db0568ccf0c866189e59c8530cc 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 28672, 28672, 2048, 1148, e564909cefb616a28b25283c825dc815 +0, 28672, 28672, 2048, 1404, 9ddf9ceb0f25e54813f340c52b78a21f 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 30720, 30720, 2048, 1277, 84bccfcecef582100f222c16d610d5e8 +0, 30720, 30720, 2048, 1550, 52ca630df0df5d29a3d4d0133e746d39 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 32768, 32768, 2048, 1325, cc3efca64cb6582b2de50edb0f504f39 +0, 32768, 32768, 2048, 1549, d999030e465c63639d2c501180ef9f63 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 34816, 34816, 2048, 1110, 2faa567250ca713c2c49c52bbec705d2 +0, 34816, 34816, 2048, 1582, 2ea6009ba8964412d0be2286296eb255 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 36864, 36864, 2048, 1150, 6c3d1e9219837fe1eca7700df25736ce +0, 36864, 36864, 2048, 1519, ba2c386a35843ce0bb25b4f5c17e2ee6 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 38912, 38912, 2048, 1209, fd6b8b2379c5cc5a05990d1bf50a2122 +0, 38912, 38912, 2048, 1541, 34e3b4b5eb4ac0a0ab1fee2df6c38007 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 40960, 40960, 2048, 1223, d54c50d04e379f767ca0600576c42f1f +0, 40960, 40960, 2048, 1578, f7c6d15a0de6088a1547d4be0898387f 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 43008, 43008, 2048, 1254, b74fd59594ea997036fb71efaaff5609 +0, 43008, 43008, 2048, 1622, e568e8b1bf951006f7d025890b950e5d 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 45056, 45056, 2048, 1080, 09fdad0d2419ce79d6058c5989545231 +0, 45056, 45056, 2048, 1611, a208ef59b6f176a78d6c9113df17cf3d 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 47104, 47104, 2048, 1096, 2ead3c39825ce9277dfb2d1588499d67 +0, 47104, 47104, 2048, 1706, f298b1930c927839470258f50d456dc8 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 49152, 49152, 2048, 9724, 91bc413e47961f3c58b3a62b0a35a725 +0, 49152, 49152, 2048, 9737, 94e0e1fa27e7e57a956e0fc27670e5c8 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 51200, 51200, 2048, 789, c77a232b086330716737047f6442e074 +0, 51200, 51200, 2048, 1323, 248d92526f1e6a0d5e7592b40ac213c0 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 53248, 53248, 2048, 1012, 24865dcc56c61c306178c451ae00b73a +0, 53248, 53248, 2048, 1621, 1ee6a5eb09be8ab281d05125c2868c56 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 55296, 55296, 2048, 1138, 8fdddcd003cd2e630aa55c7f5e76da12 +0, 55296, 55296, 2048, 1698, db8b8ca03eca285d02dbce6eaaacdfd1 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 57344, 57344, 2048, 1037, 18e607adcfb97d20a072329590bda616 +0, 57344, 57344, 2048, 1793, c50e4bdacb3ecef9c94be7b292929018 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 59392, 59392, 2048, 1070, c2d7f9699a335dd78f2c60e3ade8d2da +0, 59392, 59392, 2048, 1805, 1db64693c5ca5595b2f47097ffdfc612 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 61440, 61440, 2048, 1124, d818aa7626cd6bc9707779072a459dee +0, 61440, 61440, 2048, 1880, 9f96e1bc1f3b595d6cd626dced55416f 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 63488, 63488, 2048, 1003, e49360236a4506e1ee35070de2cab38c +0, 63488, 63488, 2048, 1902, 209393253d103d83d8dddde7fe044953 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 65536, 65536, 2048, 1013, 7649fc13088a882be2cb95bc57990723 +0, 65536, 65536, 2048, 1896, 9a845e06daafc1dd83d77fe507569968 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 67584, 67584, 2048, 1108, 1e7a69eb26b287579033939d186b1de0 +0, 67584, 67584, 2048, 1954, 77c37124c545198b688518508299f5f8 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 69632, 69632, 2048, 1164, 90562532804f73e3338280d2821c8640 +0, 69632, 69632, 2048, 1989, 0b142544ef59e421e33a40f9e685dffa 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 71680, 71680, 2048, 1126, 5ea80cfb0455babf9b19446198af206b +0, 71680, 71680, 2048, 2042, f69d73e0af0b4d9ef65205d8a0ee0937 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 73728, 73728, 2048, 8426, 3d8057fcb27ddc70720a3955571c4ac0 +0, 73728, 73728, 2048, 10838, bd02df61e3f5c0aa572904220aaf04a6 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 75776, 75776, 2048, 694, 86806974f051b415bfc0996af7f47696 +0, 75776, 75776, 2048, 1511, 6ab5a58771e346bd8756fdd68139ad8e 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 77824, 77824, 2048, 892, e71be76af5b6b046e44e3e6257f6bd92 +0, 77824, 77824, 2048, 1780, 62e0bc487aa55ad381d0a1e7f8b7a477 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 79872, 79872, 2048, 1083, 505084a26ae78907fabd463e2d05bbcb +0, 79872, 79872, 2048, 1953, ad1854098648e499e347cf828202d1d5 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 81920, 81920, 2048, 993, 0f5368f247b2cf7ecd671435aeda8b37 +0, 81920, 81920, 2048, 2036, da8405d19586da34274a578f4972fd7f 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 83968, 83968, 2048, 1003, aa87dcae3a211b2689284d222ed6db76 +0, 83968, 83968, 2048, 1980, e046fca4a3652fad1b0b22e49a290dd8 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 86016, 86016, 2048, 1032, 3386f36294719e0a5186e2f2edaf0969 +0, 86016, 86016, 2048, 2014, 01806ec06d4cdb2b840a6f7993b648e3 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 88064, 88064, 2048, 1028, 2a8be744fbdc6fe0072172c808f455c1 +0, 88064, 88064, 2048, 2040, 19c5cc70489711d467ef7ef4414fdf6a 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 90112, 90112, 2048, 948, cb1c1d28286d5030bd27b393653c4cc4 +0, 90112, 90112, 2048, 2071, 2bc9f2d22ac276366337341e89efd6cb 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 92160, 92160, 2048, 997, 2cec49ea758e4853dd5036277ae7a97c +0, 92160, 92160, 2048, 2117, 7173333f3ff643752b8afea6d5486117 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 94208, 94208, 2048, 978, 876c8edd1ceee6003ad9522fddec3791 +0, 94208, 94208, 2048, 2169, fda9c958dc9fea54efa935624528a902 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 96256, 96256, 2048, 988, 6d707c6f0fa6e525be40889cee04a737 +0, 96256, 96256, 2048, 2096, 9516005a46f05f1a582524be91c4d672 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 98304, 98304, 2048, 8690, 40627c6e6f397670bda29319b2920a6d +0, 98304, 98304, 2048, 11219, 834f992165c0ee5e5a60fff78610b449 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 100352, 100352, 2048, 635, 16962fc4bae92dda139fb107d78b8073 +0, 100352, 100352, 2048, 1506, 74f01869f22e72e244f31e2da2614676 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/shortest b/tests/ref/fate/shortest index f39a730c2c..d264955389 100644 --- a/tests/ref/fate/shortest +++ b/tests/ref/fate/shortest @@ -14,110 +14,110 @@ #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 1, 15854, 95fdffc627c15ec2a1764adb98378cc8, S=1, 8, 9cf0b40a4b63467e3c719c72a911acbd +0, 0, 0, 1, 8906, dc889f5692ac7d91295c9fbae76a9818, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 1, 1, 1, 13318, 61e9d6d30e533292ff37b1168e58ab11, S=1, 8, 36b12655a39dea3638d6feeaa38693f4 +0, 1, 1, 1, 1025, 3c8f2dba6d80ebd4f656ecb772d46c9d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 2, 2, 1, 11475, 5591622b2d2b557ff749fa736c631ff3, S=1, 8, 36b12655a39dea3638d6feeaa38693f4 +0, 2, 2, 1, 1226, 03470d542c38b78c48df45f19f2958e7, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 3, 3, 1, 11629, c06ab8d81d16477f11a03c0cac2e99dd, S=1, 8, 36b12655a39dea3638d6feeaa38693f4 +0, 3, 3, 1, 1353, 51f123ef389e7ccb20d382ce779d81ed, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 4, 4, 1, 6108, b2077a08d20772f03eb5a438a79e34d6, S=1, 8, 4057375d7213345ff8b5690075371608 +0, 4, 4, 1, 1421, 19897f392cc3517485bc6acfed2c2e2f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 5, 5, 1, 2073, f60858c134b710797b932f6bd67375e8, S=1, 8, c04afc86c8f48384ee20fca6c8e87238 +0, 5, 5, 1, 1446, 6d5a5dc31d09c144fba37c4e569f6e35, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 6, 6, 1, 1593, 722a391dbe8cec12d21c24967bcd3f9a, S=1, 8, d2344c094573d1252fd75c0ba2721f0a +0, 6, 6, 1, 1483, 299f60d66033bab84ee737c6056e8588, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 7, 7, 1, 1465, cabebc01bc61ee73be6f5877ea7dcda9, S=1, 8, 25b6cf153f1c4424af08a91be1bea2bb +0, 7, 7, 1, 1494, 54759f501f33744e81a456b5e4d695f7, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 8, 8, 1, 1306, e8cf3345ce9b5d482f8d766f657173d9, S=1, 8, d0b8916b10362671e64f1d73ba9d851e +0, 8, 8, 1, 1552, 446661f8d2ee9b82c868cffb26160054, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 9, 9, 1, 1386, e8214a31192fed1d3a610aa2ea1b5ea3, S=1, 8, 56c142e2fc6ab90d85490e3bb0b21e8d +0, 9, 9, 1, 1521, 0db5cd946c19b1552eacf56901558e5c, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 10, 10, 1, 1205, b99687be797b20ff061d1226b2d4a26b, S=1, 8, c64ed668aab56d6e18d8418938acb050 +0, 10, 10, 1, 1545, 725ac20d7c171e448dce01d660021118, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 11, 11, 1, 1317, ec1c7bfb91f1af72cc22ad37b600024c, S=1, 8, fb7cb9023f678ab152b0ece99ade9b59 +0, 11, 11, 1, 1556, 429e63d26b4b3b95b91547489e49293d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 12, 12, 1, 9546, d574659d05e5ad432928836ced7e734f, S=1, 8, 6be505c5c4671e678387ee2f3bda6994 +0, 12, 12, 1, 8689, 710c00d071339e873215f0c8b58cab0b, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 13, 13, 1, 859, 3066311e4eeb7f69a9b20939873e2424, S=1, 8, b8160789f7975e1bc3e5dc59254dc976 +0, 13, 13, 1, 1144, 74ee1db0568ccf0c866189e59c8530cc, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 14, 14, 1, 1148, e564909cefb616a28b25283c825dc815, S=1, 8, c64ed668aab56d6e18d8418938acb050 +0, 14, 14, 1, 1404, 9ddf9ceb0f25e54813f340c52b78a21f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 15, 15, 1, 1277, 84bccfcecef582100f222c16d610d5e8, S=1, 8, 4035ac4c4d4aadf545172fdb0202adc7 +0, 15, 15, 1, 1550, 52ca630df0df5d29a3d4d0133e746d39, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 16, 16, 1, 1325, cc3efca64cb6582b2de50edb0f504f39, S=1, 8, 526bb3ebd360dd8583919f24b6379b18 +0, 16, 16, 1, 1549, d999030e465c63639d2c501180ef9f63, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 17, 17, 1, 1110, 2faa567250ca713c2c49c52bbec705d2, S=1, 8, ae7b92e39e339916a550e7b0115af8ed +0, 17, 17, 1, 1582, 2ea6009ba8964412d0be2286296eb255, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 18, 18, 1, 1150, 6c3d1e9219837fe1eca7700df25736ce, S=1, 8, e2a3142bfafcd5f23e7c1a97fdcd1611 +0, 18, 18, 1, 1519, ba2c386a35843ce0bb25b4f5c17e2ee6, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 19, 19, 1, 1209, fd6b8b2379c5cc5a05990d1bf50a2122, S=1, 8, 72021a86e6819ff2770afb3a7aba9822 +0, 19, 19, 1, 1541, 34e3b4b5eb4ac0a0ab1fee2df6c38007, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 20, 20, 1, 1223, d54c50d04e379f767ca0600576c42f1f, S=1, 8, 3f3be12054d7ac9a86b58534b0f85ad5 +0, 20, 20, 1, 1578, f7c6d15a0de6088a1547d4be0898387f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 21, 21, 1, 1254, b74fd59594ea997036fb71efaaff5609, S=1, 8, 82e123514584560af379c50e566a0efd +0, 21, 21, 1, 1622, e568e8b1bf951006f7d025890b950e5d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 22, 22, 1, 1080, 09fdad0d2419ce79d6058c5989545231, S=1, 8, 1e919d1a427cacb065dec84067c18b2c +0, 22, 22, 1, 1611, a208ef59b6f176a78d6c9113df17cf3d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 23, 23, 1, 1096, 2ead3c39825ce9277dfb2d1588499d67, S=1, 8, dc6dbfeaaf3480bede1ca54281219d28 +0, 23, 23, 1, 1706, f298b1930c927839470258f50d456dc8, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 24, 24, 1, 9754, ac1468ede7c76fa49b0b5051dcb90c63, S=1, 8, f24545bac4cd7e6e3b37effde87556c1 +0, 24, 24, 1, 9767, 9a4cf29909201c67bf40238efdf65d19, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 25, 25, 1, 789, c77a232b086330716737047f6442e074, S=1, 8, dd599225f54a34977b143c70f35248af +0, 25, 25, 1, 1323, 248d92526f1e6a0d5e7592b40ac213c0, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 26, 26, 1, 1012, 24865dcc56c61c306178c451ae00b73a, S=1, 8, 431f741f44fa64eac99ceb1b820e8a04 +0, 26, 26, 1, 1621, 1ee6a5eb09be8ab281d05125c2868c56, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 27, 27, 1, 1138, 8fdddcd003cd2e630aa55c7f5e76da12, S=1, 8, dcec92442f44a3ecbaf807279b2b8699 +0, 27, 27, 1, 1698, db8b8ca03eca285d02dbce6eaaacdfd1, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 28, 28, 1, 1037, 18e607adcfb97d20a072329590bda616, S=1, 8, 309a5035c7a1ea314794289ff903b511 +0, 28, 28, 1, 1793, c50e4bdacb3ecef9c94be7b292929018, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 29, 29, 1, 1070, c2d7f9699a335dd78f2c60e3ade8d2da, S=1, 8, 6da58a82c90161d200c2e5bc66901e1c +0, 29, 29, 1, 1805, 1db64693c5ca5595b2f47097ffdfc612, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 30, 30, 1, 1124, d818aa7626cd6bc9707779072a459dee, S=1, 8, 958e599e4bc648be57b7c6e30cae8956 +0, 30, 30, 1, 1880, 9f96e1bc1f3b595d6cd626dced55416f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 31, 31, 1, 1003, e49360236a4506e1ee35070de2cab38c, S=1, 8, e57ab3c3dd96d50ef19af0d10b633f4c +0, 31, 31, 1, 1902, 209393253d103d83d8dddde7fe044953, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 32, 32, 1, 1013, 7649fc13088a882be2cb95bc57990723, S=1, 8, fd54d6fc3ca45da8e73507b3cec3bdb4 +0, 32, 32, 1, 1896, 9a845e06daafc1dd83d77fe507569968, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 33, 33, 1, 1108, 1e7a69eb26b287579033939d186b1de0, S=1, 8, 9362b100a77fad014652eafe0eb1944d +0, 33, 33, 1, 1954, 77c37124c545198b688518508299f5f8, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 34, 34, 1, 1164, 90562532804f73e3338280d2821c8640, S=1, 8, 5c5abe1da5ff1a6a0566a7cb45b02c08 +0, 34, 34, 1, 1989, 0b142544ef59e421e33a40f9e685dffa, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 35, 35, 1, 1126, 5ea80cfb0455babf9b19446198af206b, S=1, 8, c281971cbe0832b1c13585320ff035ea +0, 35, 35, 1, 2042, f69d73e0af0b4d9ef65205d8a0ee0937, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 36, 36, 1, 8456, c7a47c871310914cfc32663cf24166d7, S=1, 8, 3e24aaf4c9d5c084d3a3f0d90f783278 +0, 36, 36, 1, 10868, 2f4b959d1dc05a1d7e00cbe204b5fc2d, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 37, 37, 1, 694, 86806974f051b415bfc0996af7f47696, S=1, 8, 540ee8ae462556d0a046a736f297b173 +0, 37, 37, 1, 1511, 6ab5a58771e346bd8756fdd68139ad8e, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 38, 38, 1, 892, e71be76af5b6b046e44e3e6257f6bd92, S=1, 8, fc560de809ee8241e933ecd2661108b7 +0, 38, 38, 1, 1780, 62e0bc487aa55ad381d0a1e7f8b7a477, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 39, 39, 1, 1083, 505084a26ae78907fabd463e2d05bbcb, S=1, 8, 049eee0ee70335df57ac59af203fe219 +0, 39, 39, 1, 1953, ad1854098648e499e347cf828202d1d5, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 40, 40, 1, 993, 0f5368f247b2cf7ecd671435aeda8b37, S=1, 8, 5550ac360fd5ed3a21840259f1a93025 +0, 40, 40, 1, 2036, da8405d19586da34274a578f4972fd7f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 41, 41, 1, 1003, aa87dcae3a211b2689284d222ed6db76, S=1, 8, 95a7c655a3d4711b01b9d5cd871d1f30 +0, 41, 41, 1, 1980, e046fca4a3652fad1b0b22e49a290dd8, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 42, 42, 1, 1032, 3386f36294719e0a5186e2f2edaf0969, S=1, 8, 396a23cdb4b96b8b77886469409ad7ca +0, 42, 42, 1, 2014, 01806ec06d4cdb2b840a6f7993b648e3, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 43, 43, 1, 1028, 2a8be744fbdc6fe0072172c808f455c1, S=1, 8, 4fda569b89ad069d7b82b585cd6ff009 +0, 43, 43, 1, 2040, 19c5cc70489711d467ef7ef4414fdf6a, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 44, 44, 1, 948, cb1c1d28286d5030bd27b393653c4cc4, S=1, 8, 5b4d66a595207277db45b6ecd9b08854 +0, 44, 44, 1, 2071, 2bc9f2d22ac276366337341e89efd6cb, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 45, 45, 1, 997, 2cec49ea758e4853dd5036277ae7a97c, S=1, 8, 28a85a0ee15dc8c5b5b69d882ad55a29 +0, 45, 45, 1, 2117, 7173333f3ff643752b8afea6d5486117, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 46, 46, 1, 978, 876c8edd1ceee6003ad9522fddec3791, S=1, 8, f2b52b616d3de191e5ae7389d57f5ab2 +0, 46, 46, 1, 2169, fda9c958dc9fea54efa935624528a902, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 47, 47, 1, 988, 6d707c6f0fa6e525be40889cee04a737, S=1, 8, 720720daf8bcb72639ee2b9a3af9ce83 +0, 47, 47, 1, 2096, 9516005a46f05f1a582524be91c4d672, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 48, 48, 1, 8720, 5e230de451b13a8fbfd0432da23ab6b3, S=1, 8, 997caa31a1cdf2d03b5d243cd0755949 +0, 48, 48, 1, 11249, 36825ee3b6f996a93b1031bd1106586a, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 49, 49, 1, 635, 16962fc4bae92dda139fb107d78b8073, S=1, 8, f9e79a0c8a7a7796e9adf5f4f3c48102 +0, 49, 49, 1, 1506, 74f01869f22e72e244f31e2da2614676, S=1, 8, f6ebfc548ad9ba3d00b655047277212d 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d From bb89a2f64fd1d74cc51af62d5ef133be274dd7af Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 29 Nov 2021 17:41:16 +0100 Subject: [PATCH 328/894] avcodec/movtextenc: Fix infinite loop due to variable truncation Regression since af043b839c38e850af1184fd6be691f8475c048e. Fixes ticket #9409. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 2ae5a9bf0b..0632463a63 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -84,7 +84,7 @@ typedef struct { uint8_t box_flags; StyleBox d; uint16_t text_pos; - uint16_t byte_count; + unsigned byte_count; char **fonts; int font_count; double font_scale_factor; @@ -584,9 +584,9 @@ static void mov_text_cancel_overrides_cb(void *priv, const char *style_name) mov_text_ass_style_set(s, style); } -static uint16_t utf8_strlen(const char *text, int len) +static unsigned utf8_strlen(const char *text, int len) { - uint16_t i = 0, ret = 0; + unsigned i = 0, ret = 0; while (i < len) { char c = text[i]; if ((c & 0x80) == 0) @@ -606,7 +606,7 @@ static uint16_t utf8_strlen(const char *text, int len) static void mov_text_text_cb(void *priv, const char *text, int len) { - uint16_t utf8_len = utf8_strlen(text, len); + unsigned utf8_len = utf8_strlen(text, len); MovTextContext *s = priv; av_bprint_append_data(&s->buffer, text, len); // If it's not utf-8, just use the byte length From 0b934f8f17c19be6b73cc5ecc9a23f7451bee5d0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 09:24:51 +0100 Subject: [PATCH 329/894] avcodec/movtextenc: Reset AVBPrint at the beginning, not end of encoding This avoids abusing a variable called length for the return value and ensures that the AVBPrint is always reset before using it; previously this has been forgotten in some error paths. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 0632463a63..46109e0a5e 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -646,6 +646,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, s->text_pos = 0; s->count = 0; s->box_flags = 0; + av_bprint_clear(&s->buffer); for (i = 0; i < sub->num_rects; i++) { const char *ass = sub->rects[i]->ass; @@ -669,27 +670,20 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, AV_WB16(buf, s->byte_count); buf += 2; - if (!av_bprint_is_complete(&s->buffer)) { - length = AVERROR(ENOMEM); - goto exit; - } + if (!av_bprint_is_complete(&s->buffer)) + return AVERROR(ENOMEM); - if (!s->buffer.len) { - length = 0; - goto exit; - } + if (!s->buffer.len) + return 0; if (s->buffer.len > bufsize - 3) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - length = AVERROR_BUFFER_TOO_SMALL; - goto exit; + return AVERROR_BUFFER_TOO_SMALL; } memcpy(buf, s->buffer.str, s->buffer.len); length = s->buffer.len + 2; -exit: - av_bprint_clear(&s->buffer); return length; } From f8e5e1c52333e6c330fbb4fe8ec2cb07240ca8c5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 09:21:35 +0100 Subject: [PATCH 330/894] avcodec/movtextenc: Check for too long subtitles Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 46109e0a5e..eecadaf503 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -667,6 +667,8 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, } } + if (s->byte_count > UINT16_MAX) + return AVERROR(ERANGE); AV_WB16(buf, s->byte_count); buf += 2; From 0bc3c070fb516319f08d7264af27e3e123f45e95 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 10:02:13 +0100 Subject: [PATCH 331/894] avcodec/movtextenc: Fix encoding of subtitles with multiple rects The format of a mov_text (3GPP Timed Text) sample is: uint16_t text_length; uint8_t text[text_length]; TextSampleModifierBox text_modifier; Yet in case our encoder receives an AVSubtitle with multiple ASS AVSubtitleRects, it creates something like this: uint16_t text_length; uint8_t text[text_length_1]; TextSampleModifierBox text_modifier_1; uint8_t text[text_length_2]; TextSampleModifierBox text_modifier_2; ... where text_length is the sum of all the text_length_*. This commit fixes this by writing the TextSampleModifierBoxes only after all the rects have been written. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index eecadaf503..52e51503d6 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -640,7 +640,6 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, MovTextContext *s = avctx->priv_data; ASSDialog *dialog; int i, length; - size_t j; s->byte_count = 0; s->text_pos = 0; @@ -661,10 +660,6 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, mov_text_dialog(s, dialog); ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); ff_ass_free_dialog(&dialog); - - for (j = 0; j < box_count; j++) { - box_types[j].encode(s); - } } if (s->byte_count > UINT16_MAX) @@ -672,6 +667,9 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, AV_WB16(buf, s->byte_count); buf += 2; + for (size_t j = 0; j < box_count; j++) + box_types[j].encode(s); + if (!av_bprint_is_complete(&s->buffer)) return AVERROR(ENOMEM); From c4c9d096ae11535dc16e5f61e062b9bda056db3d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 11:05:52 +0100 Subject: [PATCH 332/894] avcodec/movtextenc: Remove redundant byte count Use the AVBPrint's len instead. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 52e51503d6..112af41093 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -84,7 +84,6 @@ typedef struct { uint8_t box_flags; StyleBox d; uint16_t text_pos; - unsigned byte_count; char **fonts; int font_count; double font_scale_factor; @@ -611,7 +610,6 @@ static void mov_text_text_cb(void *priv, const char *text, int len) av_bprint_append_data(&s->buffer, text, len); // If it's not utf-8, just use the byte length s->text_pos += utf8_len ? utf8_len : len; - s->byte_count += len; } static void mov_text_new_line_cb(void *priv, int forced) @@ -619,7 +617,6 @@ static void mov_text_new_line_cb(void *priv, int forced) MovTextContext *s = priv; av_bprint_append_data(&s->buffer, "\n", 1); s->text_pos += 1; - s->byte_count += 1; } static const ASSCodesCallbacks mov_text_callbacks = { @@ -641,7 +638,6 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, ASSDialog *dialog; int i, length; - s->byte_count = 0; s->text_pos = 0; s->count = 0; s->box_flags = 0; @@ -662,9 +658,9 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, ff_ass_free_dialog(&dialog); } - if (s->byte_count > UINT16_MAX) + if (s->buffer.len > UINT16_MAX) return AVERROR(ERANGE); - AV_WB16(buf, s->byte_count); + AV_WB16(buf, s->buffer.len); buf += 2; for (size_t j = 0; j < box_count; j++) From acdfc4bdfb1d800e9459ce700538f09174502d7e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 11:08:33 +0100 Subject: [PATCH 333/894] avcodec/movtextenc: Simplify writing a single char Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 112af41093..5869942ec0 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -615,8 +615,8 @@ static void mov_text_text_cb(void *priv, const char *text, int len) static void mov_text_new_line_cb(void *priv, int forced) { MovTextContext *s = priv; - av_bprint_append_data(&s->buffer, "\n", 1); s->text_pos += 1; + av_bprint_chars(&s->buffer, '\n', 1); } static const ASSCodesCallbacks mov_text_callbacks = { From 11b11577fe801b6afb7b4f46a5e5df853f7c1557 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 22 Nov 2021 11:44:24 +0100 Subject: [PATCH 334/894] avfilter: add audio spectral stats filter --- Changelog | 1 + doc/filters.texi | 63 ++++ libavfilter/Makefile | 1 + libavfilter/af_aspectralstats.c | 605 ++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 672 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_aspectralstats.c diff --git a/Changelog b/Changelog index 648079ab64..f6b9802034 100644 --- a/Changelog +++ b/Changelog @@ -36,6 +36,7 @@ version : - VideoToolbox VP9 hwaccel - VideoToolbox ProRes hwaccel - support loongarch. +- aspectralstats audio filter version 4.4: diff --git a/doc/filters.texi b/doc/filters.texi index a1b212d38a..9ddff533de 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2695,6 +2695,69 @@ Set oversampling factor. This filter supports the all above options as @ref{commands}. +@section aspectralstats + +Display frequency domain statistical information about the audio channels. +Statistics are calculated and stored as metadata for each audio channel and for each audio frame. + +It accepts the following option: +@table @option +@item win_size +Set the window length in samples. Default value is 2048. +Allowed range is from 32 to 65536. + +@item win_func +Set window function. + +It accepts the following values: +@table @samp +@item rect +@item bartlett +@item hann, hanning +@item hamming +@item blackman +@item welch +@item flattop +@item bharris +@item bnuttall +@item bhann +@item sine +@item nuttall +@item lanczos +@item gauss +@item tukey +@item dolph +@item cauchy +@item parzen +@item poisson +@item bohman +@end table +Default is @code{hann}. + +@item overlap +Set window overlap. Allowed range is from @code{0} +to @code{1}. Default value is @code{0.5}. + +@end table + +A list of each metadata key follows: + +@table @option +@item mean +@item variance +@item centroid +@item spread +@item skewness +@item kurtosis +@item entropy +@item flatness +@item crest +@item flux +@item slope +@item decrease +@item rolloff +@end table + @section asr Automatic Speech Recognition diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 0e27aeeff6..551d13aadc 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -92,6 +92,7 @@ OBJS-$(CONFIG_ASETTB_FILTER) += settb.o OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o OBJS-$(CONFIG_ASIDEDATA_FILTER) += f_sidedata.o OBJS-$(CONFIG_ASOFTCLIP_FILTER) += af_asoftclip.o +OBJS-$(CONFIG_ASPECTRALSTATS_FILTER) += af_aspectralstats.o OBJS-$(CONFIG_ASPLIT_FILTER) += split.o OBJS-$(CONFIG_ASR_FILTER) += af_asr.o OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o diff --git a/libavfilter/af_aspectralstats.c b/libavfilter/af_aspectralstats.c new file mode 100644 index 0000000000..da418d22bf --- /dev/null +++ b/libavfilter/af_aspectralstats.c @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2021 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/audio_fifo.h" +#include "libavutil/opt.h" +#include "libavutil/tx.h" +#include "audio.h" +#include "avfilter.h" +#include "filters.h" +#include "internal.h" +#include "window_func.h" + +typedef struct ChannelSpectralStats { + float mean; + float variance; + float centroid; + float spread; + float skewness; + float kurtosis; + float entropy; + float flatness; + float crest; + float flux; + float slope; + float decrease; + float rolloff; +} ChannelSpectralStats; + +typedef struct AudioSpectralStatsContext { + const AVClass *class; + int win_size; + int win_func; + float overlap; + int nb_channels; + int hop_size; + ChannelSpectralStats *stats; + AVAudioFifo *fifo; + float *window_func_lut; + int64_t pts; + int eof; + av_tx_fn tx_fn; + AVTXContext **fft; + AVComplexFloat **fft_in; + AVComplexFloat **fft_out; + float **prev_magnitude; + float **magnitude; +} AudioSpectralStatsContext; + +#define OFFSET(x) offsetof(AudioSpectralStatsContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption aspectralstats_options[] = { + { "win_size", "set the window size", OFFSET(win_size), AV_OPT_TYPE_INT, {.i64=2048}, 32, 65536, A }, + WIN_FUNC_OPTION("win_func", OFFSET(win_func), A, WFUNC_HANNING), + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(aspectralstats); + +static int config_output(AVFilterLink *outlink) +{ + AudioSpectralStatsContext *s = outlink->src->priv; + float overlap, scale; + int ret; + + s->nb_channels = outlink->channels; + s->fifo = av_audio_fifo_alloc(outlink->format, s->nb_channels, s->win_size); + if (!s->fifo) + return AVERROR(ENOMEM); + + s->window_func_lut = av_realloc_f(s->window_func_lut, s->win_size, + sizeof(*s->window_func_lut)); + if (!s->window_func_lut) + return AVERROR(ENOMEM); + generate_window_func(s->window_func_lut, s->win_size, s->win_func, &overlap); + if (s->overlap == 1.f) + s->overlap = overlap; + + s->hop_size = s->win_size * (1.f - s->overlap); + if (s->hop_size <= 0) + return AVERROR(EINVAL); + + s->stats = av_calloc(s->nb_channels, sizeof(*s->stats)); + if (!s->stats) + return AVERROR(ENOMEM); + + s->fft = av_calloc(s->nb_channels, sizeof(*s->fft)); + if (!s->fft) + return AVERROR(ENOMEM); + + s->magnitude = av_calloc(s->nb_channels, sizeof(*s->magnitude)); + if (!s->magnitude) + return AVERROR(ENOMEM); + + s->prev_magnitude = av_calloc(s->nb_channels, sizeof(*s->prev_magnitude)); + if (!s->prev_magnitude) + return AVERROR(ENOMEM); + + s->fft_in = av_calloc(s->nb_channels, sizeof(*s->fft_in)); + if (!s->fft_in) + return AVERROR(ENOMEM); + + s->fft_out = av_calloc(s->nb_channels, sizeof(*s->fft_out)); + if (!s->fft_out) + return AVERROR(ENOMEM); + + for (int ch = 0; ch < s->nb_channels; ch++) { + ret = av_tx_init(&s->fft[ch], &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->win_size, &scale, 0); + if (ret < 0) + return ret; + + s->fft_in[ch] = av_calloc(s->win_size, sizeof(**s->fft_in)); + if (!s->fft_in[ch]) + return AVERROR(ENOMEM); + + s->fft_out[ch] = av_calloc(s->win_size, sizeof(**s->fft_out)); + if (!s->fft_out[ch]) + return AVERROR(ENOMEM); + + s->magnitude[ch] = av_calloc(s->win_size, sizeof(**s->magnitude)); + if (!s->magnitude[ch]) + return AVERROR(ENOMEM); + + s->prev_magnitude[ch] = av_calloc(s->win_size, sizeof(**s->prev_magnitude)); + if (!s->prev_magnitude[ch]) + return AVERROR(ENOMEM); + } + + return 0; +} + +static void set_meta(AVDictionary **metadata, int chan, const char *key, + const char *fmt, float val) +{ + uint8_t value[128]; + uint8_t key2[128]; + + snprintf(value, sizeof(value), fmt, val); + if (chan) + snprintf(key2, sizeof(key2), "lavfi.aspectralstats.%d.%s", chan, key); + else + snprintf(key2, sizeof(key2), "lavfi.aspectralstats.%s", key); + av_dict_set(metadata, key2, value, 0); +} + +static void set_metadata(AudioSpectralStatsContext *s, AVDictionary **metadata) +{ + for (int ch = 0; ch < s->nb_channels; ch++) { + ChannelSpectralStats *stats = &s->stats[ch]; + + set_meta(metadata, ch + 1, "mean", "%g", stats->mean); + set_meta(metadata, ch + 1, "variance", "%g", stats->variance); + set_meta(metadata, ch + 1, "centroid", "%g", stats->centroid); + set_meta(metadata, ch + 1, "spread", "%g", stats->spread); + set_meta(metadata, ch + 1, "skewness", "%g", stats->skewness); + set_meta(metadata, ch + 1, "kurtosis", "%g", stats->kurtosis); + set_meta(metadata, ch + 1, "entropy", "%g", stats->entropy); + set_meta(metadata, ch + 1, "flatness", "%g", stats->flatness); + set_meta(metadata, ch + 1, "crest", "%g", stats->crest); + set_meta(metadata, ch + 1, "flux", "%g", stats->flux); + set_meta(metadata, ch + 1, "slope", "%g", stats->slope); + set_meta(metadata, ch + 1, "decrease", "%g", stats->decrease); + set_meta(metadata, ch + 1, "rolloff", "%g", stats->rolloff); + } +} + +static float spectral_mean(const float *const spectral, int size, int max_freq) +{ + float sum = 0.f; + + for (int n = 0; n < size; n++) + sum += spectral[n]; + + return sum / size; +} + +static float sqrf(float a) +{ + return a * a; +} + +static float spectral_variance(const float *const spectral, int size, int max_freq, float mean) +{ + float sum = 0.f; + + for (int n = 0; n < size; n++) + sum += sqrf(spectral[n] - mean); + + return sum / size; +} + +static float spectral_centroid(const float *const spectral, int size, int max_freq) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * n * scale; + den += spectral[n]; + } + + if (den <= FLT_EPSILON) + return 1.f; + return num / den; +} + +static float spectral_spread(const float *const spectral, int size, int max_freq, float centroid) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * sqrf(n * scale - centroid); + den += spectral[n]; + } + + if (den <= FLT_EPSILON) + return 1.f; + return sqrtf(num / den); +} + +static float cbrf(float a) +{ + return a * a * a; +} + +static float spectral_skewness(const float *const spectral, int size, int max_freq, float centroid, float spread) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * cbrf(n * scale - centroid); + den += spectral[n]; + } + + den *= cbrf(spread); + if (den <= FLT_EPSILON) + return 1.f; + return num / den; +} + +static float spectral_kurtosis(const float *const spectral, int size, int max_freq, float centroid, float spread) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * sqrf(sqrf(n * scale - centroid)); + den += spectral[n]; + } + + den *= sqrf(sqrf(spread)); + if (den <= FLT_EPSILON) + return 1.f; + return num / den; +} + +static float spectral_entropy(const float *const spectral, int size, int max_freq) +{ + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * logf(spectral[n] + FLT_EPSILON); + } + + den = logf(size); + if (den <= FLT_EPSILON) + return 1.f; + return -num / den; +} + +static float spectral_flatness(const float *const spectral, int size, int max_freq) +{ + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + float v = FLT_EPSILON + spectral[n]; + num += logf(v); + den += v; + } + + num /= size; + den /= size; + num = expf(num); + if (den <= FLT_EPSILON) + return 0.f; + return num / den; +} + +static float spectral_crest(const float *const spectral, int size, int max_freq) +{ + float max = 0.f, mean = 0.f; + + for (int n = 0; n < size; n++) { + max = fmaxf(max, spectral[n]); + mean += spectral[n]; + } + + mean /= size; + if (mean <= FLT_EPSILON) + return 0.f; + return max / mean; +} + +static float spectral_flux(const float *const spectral, const float *const prev_spectral, + int size, int max_freq) +{ + float sum = 0.f; + + for (int n = 0; n < size; n++) + sum += sqrf(spectral[n] - prev_spectral[n]); + + return sqrtf(sum); +} + +static float spectral_slope(const float *const spectral, int size, int max_freq) +{ + const float mean_freq = size * 0.5f; + float mean_spectral = 0.f, num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) + mean_spectral += spectral[n]; + mean_spectral /= size; + + for (int n = 0; n < size; n++) { + num += ((n - mean_freq) / mean_freq) * (spectral[n] - mean_spectral); + den += sqrf((n - mean_freq) / mean_freq); + } + + if (fabsf(den) <= FLT_EPSILON) + return 0.f; + return num / den; +} + +static float spectral_decrease(const float *const spectral, int size, int max_freq) +{ + float num = 0.f, den = 0.f; + + for (int n = 1; n < size; n++) { + num += (spectral[n] - spectral[0]) / n; + den += spectral[n]; + } + + if (den <= FLT_EPSILON) + return 0.f; + return num / den; +} + +static float spectral_rolloff(const float *const spectral, int size, int max_freq) +{ + const float scale = max_freq / (float)size; + float norm = 0.f, sum = 0.f; + int idx = 0.f; + + for (int n = 0; n < size; n++) + norm += spectral[n]; + norm *= 0.85f; + + for (int n = 0; n < size; n++) { + sum += spectral[n]; + if (sum >= norm) { + idx = n; + break; + } + } + + return idx * scale; +} + +static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioSpectralStatsContext *s = ctx->priv; + AVFrame *in = arg; + const int channels = s->nb_channels; + const int samples = in->nb_samples; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) { + const float *const src = (const float *const)in->extended_data[ch]; + ChannelSpectralStats *stats = &s->stats[ch]; + AVComplexFloat *fft_out = s->fft_out[ch]; + AVComplexFloat *fft_in = s->fft_in[ch]; + float *magnitude = s->magnitude[ch]; + float *prev_magnitude = s->prev_magnitude[ch]; + const float scale = 1.f / s->win_size; + + for (int n = 0; n < samples; n++) { + fft_in[n].re = src[n] * s->window_func_lut[n]; + fft_in[n].im = 0; + } + + for (int n = in->nb_samples; n < s->win_size; n++) { + fft_in[n].re = 0; + fft_in[n].im = 0; + } + + s->tx_fn(s->fft[ch], fft_out, fft_in, sizeof(float)); + + for (int n = 0; n < s->win_size / 2; n++) { + fft_out[n].re *= scale; + fft_out[n].im *= scale; + } + + for (int n = 0; n < s->win_size / 2; n++) + magnitude[n] = hypotf(fft_out[n].re, fft_out[n].im); + + stats->mean = spectral_mean(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->variance = spectral_variance(magnitude, s->win_size / 2, in->sample_rate / 2, stats->mean); + stats->centroid = spectral_centroid(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->spread = spectral_spread(magnitude, s->win_size / 2, in->sample_rate / 2, stats->centroid); + stats->skewness = spectral_skewness(magnitude, s->win_size / 2, in->sample_rate / 2, stats->centroid, stats->spread); + stats->kurtosis = spectral_kurtosis(magnitude, s->win_size / 2, in->sample_rate / 2, stats->centroid, stats->spread); + stats->entropy = spectral_entropy(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->flatness = spectral_flatness(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->crest = spectral_crest(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->flux = spectral_flux(magnitude, prev_magnitude, s->win_size / 2, in->sample_rate / 2); + stats->slope = spectral_slope(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->decrease = spectral_decrease(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->rolloff = spectral_rolloff(magnitude, s->win_size / 2, in->sample_rate / 2); + + memcpy(prev_magnitude, magnitude, s->win_size * sizeof(float)); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioSpectralStatsContext *s = ctx->priv; + AVDictionary **metadata; + AVFrame *out, *in = NULL; + int ret = 0; + + out = ff_get_audio_buffer(outlink, s->hop_size); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if (!in) { + in = ff_get_audio_buffer(outlink, s->win_size); + if (!in) + return AVERROR(ENOMEM); + } + + ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, s->win_size); + if (ret < 0) + goto fail; + + metadata = &out->metadata; + ff_filter_execute(ctx, filter_channel, in, NULL, + FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + + set_metadata(s, metadata); + + out->pts = s->pts; + s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); + + av_audio_fifo_read(s->fifo, (void **)out->extended_data, s->hop_size); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + return ret < 0 ? ret : 0; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AudioSpectralStatsContext *s = ctx->priv; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (!s->eof && av_audio_fifo_size(s->fifo) < s->win_size) { + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + + if (ret > 0) { + ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, + in->nb_samples); + if (ret >= 0 && s->pts == AV_NOPTS_VALUE) + s->pts = in->pts; + + av_frame_free(&in); + if (ret < 0) + return ret; + } + } + + if ((av_audio_fifo_size(s->fifo) >= s->win_size) || + (av_audio_fifo_size(s->fifo) > 0 && s->eof)) { + ret = filter_frame(inlink); + if (av_audio_fifo_size(s->fifo) >= s->win_size) + ff_filter_set_ready(ctx, 100); + return ret; + } + + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + s->eof = 1; + if (av_audio_fifo_size(s->fifo) >= 0) { + ff_filter_set_ready(ctx, 100); + return 0; + } + } + } + + if (s->eof && av_audio_fifo_size(s->fifo) <= 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; + } + + if (!s->eof) + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioSpectralStatsContext *s = ctx->priv; + + for (int ch = 0; ch < s->nb_channels; ch++) { + if (s->fft) + av_tx_uninit(&s->fft[ch]); + if (s->fft_in) + av_freep(&s->fft_in[ch]); + if (s->fft_out) + av_freep(&s->fft_out[ch]); + if (s->magnitude) + av_freep(&s->magnitude[ch]); + if (s->prev_magnitude) + av_freep(&s->prev_magnitude[ch]); + } + + av_freep(&s->fft); + av_freep(&s->magnitude); + av_freep(&s->prev_magnitude); + av_freep(&s->fft_in); + av_freep(&s->fft_out); + av_freep(&s->stats); + + av_freep(&s->window_func_lut); + av_audio_fifo_free(s->fifo); + s->fifo = NULL; +} + +static const AVFilterPad aspectralstats_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +static const AVFilterPad aspectralstats_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, +}; + +const AVFilter ff_af_aspectralstats = { + .name = "aspectralstats", + .description = NULL_IF_CONFIG_SMALL("Show frequency domain statistics about audio frames."), + .priv_size = sizeof(AudioSpectralStatsContext), + .priv_class = &aspectralstats_class, + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(aspectralstats_inputs), + FILTER_OUTPUTS(aspectralstats_outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 4bf17ef292..00c36c3f63 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -85,6 +85,7 @@ extern const AVFilter ff_af_asettb; extern const AVFilter ff_af_ashowinfo; extern const AVFilter ff_af_asidedata; extern const AVFilter ff_af_asoftclip; +extern const AVFilter ff_af_aspectralstats; extern const AVFilter ff_af_asplit; extern const AVFilter ff_af_asr; extern const AVFilter ff_af_astats; diff --git a/libavfilter/version.h b/libavfilter/version.h index b9e610ea1f..e0bdcb836d 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 17 +#define LIBAVFILTER_VERSION_MINOR 18 #define LIBAVFILTER_VERSION_MICRO 100 From fc9a6866880661b8418c728e6a54515157481875 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 25 Nov 2021 19:30:32 +0100 Subject: [PATCH 335/894] avfilter: add audio dynamic smooth filter --- Changelog | 1 + doc/filters.texi | 20 +++++ libavfilter/Makefile | 1 + libavfilter/af_adynamicsmooth.c | 142 ++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + 5 files changed, 165 insertions(+) create mode 100644 libavfilter/af_adynamicsmooth.c diff --git a/Changelog b/Changelog index f6b9802034..9bdb51443b 100644 --- a/Changelog +++ b/Changelog @@ -37,6 +37,7 @@ version : - VideoToolbox ProRes hwaccel - support loongarch. - aspectralstats audio filter +- adynamicsmooth audio filter version 4.4: diff --git a/doc/filters.texi b/doc/filters.texi index 9ddff533de..3edf3f50b0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -843,6 +843,26 @@ Compute derivative/integral of audio stream. Applying both filters one after another produces original audio. +@section adynamicsmooth + +Apply dynamic smoothing to input audio stream. + +A description of the accepted options follows. + +@table @option +@item sensitivity +Set an amount of sensitivity to frequency fluctations. Default is 2. +Allowed range is from 0 to 1e+06. + +@item basefreq +Set a base frequency for smoothing. Default value is 22050. +Allowed range is from 2 to 1e+06. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section aecho Apply echoing to the input audio. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 551d13aadc..c8082c4a2f 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -44,6 +44,7 @@ OBJS-$(CONFIG_ADECORRELATE_FILTER) += af_adecorrelate.o OBJS-$(CONFIG_ADELAY_FILTER) += af_adelay.o OBJS-$(CONFIG_ADENORM_FILTER) += af_adenorm.o OBJS-$(CONFIG_ADERIVATIVE_FILTER) += af_aderivative.o +OBJS-$(CONFIG_ADYNAMICSMOOTH_FILTER) += af_adynamicsmooth.o OBJS-$(CONFIG_AECHO_FILTER) += af_aecho.o OBJS-$(CONFIG_AEMPHASIS_FILTER) += af_aemphasis.o OBJS-$(CONFIG_AEVAL_FILTER) += aeval.o diff --git a/libavfilter/af_adynamicsmooth.c b/libavfilter/af_adynamicsmooth.c new file mode 100644 index 0000000000..4e00fecc6a --- /dev/null +++ b/libavfilter/af_adynamicsmooth.c @@ -0,0 +1,142 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct AudioDynamicSmoothContext { + const AVClass *class; + + double sensitivity; + double basefreq; + + AVFrame *coeffs; +} AudioDynamicSmoothContext; + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioDynamicSmoothContext *s = ctx->priv; + + s->coeffs = ff_get_audio_buffer(inlink, 3); + if (!s->coeffs) + return AVERROR(ENOMEM); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioDynamicSmoothContext *s = ctx->priv; + const double sensitivity = s->sensitivity; + const double wc = s->basefreq / in->sample_rate; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + for (int ch = 0; ch < out->channels; ch++) { + const double *src = (const double *)in->extended_data[ch]; + double *dst = (double *)out->extended_data[ch]; + double *coeffs = (double *)s->coeffs->extended_data[ch]; + double low1 = coeffs[0]; + double low2 = coeffs[1]; + double inz = coeffs[2]; + + for (int n = 0; n < out->nb_samples; n++) { + double low1z = low1; + double low2z = low2; + double bandz = low2z - low1z; + double wd = wc + sensitivity * fabs(bandz); + double g = fmin(1., wd * (5.9948827 + wd * (-11.969296 + wd * 15.959062))); + + low1 = low1z + g * (0.5 * (src[n] + inz) - low1z); + low2 = low2z + g * (0.5 * (low1 + low1z) - low2z); + inz = src[n]; + dst[n] = ctx->is_disabled ? src[n] : low2; + } + + coeffs[0] = low1; + coeffs[1] = low2; + coeffs[2] = inz; + } + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioDynamicSmoothContext *s = ctx->priv; + + av_frame_free(&s->coeffs); +} + +#define OFFSET(x) offsetof(AudioDynamicSmoothContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption adynamicsmooth_options[] = { + { "sensitivity", "set smooth sensitivity", OFFSET(sensitivity), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 1000000, FLAGS }, + { "basefreq", "set base frequency", OFFSET(basefreq), AV_OPT_TYPE_DOUBLE, {.dbl=22050}, 2, 1000000, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(adynamicsmooth); + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +const AVFilter ff_af_adynamicsmooth = { + .name = "adynamicsmooth", + .description = NULL_IF_CONFIG_SMALL("Apply Dynamic Smoothing of input audio."), + .priv_size = sizeof(AudioDynamicSmoothContext), + .priv_class = &adynamicsmooth_class, + .uninit = uninit, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 00c36c3f63..c5c0e9b28b 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -37,6 +37,7 @@ extern const AVFilter ff_af_adecorrelate; extern const AVFilter ff_af_adelay; extern const AVFilter ff_af_adenorm; extern const AVFilter ff_af_aderivative; +extern const AVFilter ff_af_adynamicsmooth; extern const AVFilter ff_af_aecho; extern const AVFilter ff_af_aemphasis; extern const AVFilter ff_af_aeval; From bdfb0e4da414c0ff4c663fa077b15730b44482df Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Fri, 26 Nov 2021 17:10:57 +0800 Subject: [PATCH 336/894] avfilter: add a flip_vulkan filter This filter flips the input video both horizontally and vertically in one compute pipeline, and it's no need to use two pipelines for hflip_vulkan,vflip_vulkan anymore. Signed-off-by: Wu Jianhua --- configure | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_flip_vulkan.c | 61 +++++++++++++++++++++++++++++------- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/configure b/configure index aa94c39419..a98a18abaa 100755 --- a/configure +++ b/configure @@ -3631,6 +3631,7 @@ fftdnoiz_filter_select="fft" find_rect_filter_deps="avcodec avformat gpl" firequalizer_filter_deps="avcodec" firequalizer_filter_select="rdft" +flip_vulkan_filter_deps="vulkan spirv_compiler" flite_filter_deps="libflite" framerate_filter_select="scene_sad" freezedetect_filter_select="scene_sad" diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index c5c0e9b28b..2f91562aa2 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -265,6 +265,7 @@ extern const AVFilter ff_vf_fieldmatch; extern const AVFilter ff_vf_fieldorder; extern const AVFilter ff_vf_fillborders; extern const AVFilter ff_vf_find_rect; +extern const AVFilter ff_vf_flip_vulkan; extern const AVFilter ff_vf_floodfill; extern const AVFilter ff_vf_format; extern const AVFilter ff_vf_fps; diff --git a/libavfilter/vf_flip_vulkan.c b/libavfilter/vf_flip_vulkan.c index e9e04db91b..0223786ef1 100644 --- a/libavfilter/vf_flip_vulkan.c +++ b/libavfilter/vf_flip_vulkan.c @@ -26,7 +26,8 @@ enum FlipType { FLIP_VERTICAL, - FLIP_HORIZONTAL + FLIP_HORIZONTAL, + FLIP_BOTH }; typedef struct FlipVulkanContext { @@ -104,6 +105,9 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType case FLIP_VERTICAL: GLSLF(2, vec4 res = texture(input_image[%i], ivec2(pos.x, size.y - pos.y)); ,i); break; + case FLIP_BOTH: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.xy - pos.xy));, i); + break; default: GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); break; @@ -226,7 +230,7 @@ fail: return err; } -static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) +static int filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) { int err; AVFrame *out = NULL; @@ -259,14 +263,27 @@ fail: static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) { - return flip_vulkan_filter_frame(link, in, FLIP_HORIZONTAL); + return filter_frame(link, in, FLIP_HORIZONTAL); } static int vflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) { - return flip_vulkan_filter_frame(link, in, FLIP_VERTICAL); + return filter_frame(link, in, FLIP_VERTICAL); } +static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return filter_frame(link, in, FLIP_BOTH); +} + +static const AVFilterPad flip_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + } +}; + static const AVOption hflip_vulkan_options[] = { { NULL }, }; @@ -282,14 +299,6 @@ static const AVFilterPad hflip_vulkan_inputs[] = { } }; -static const AVFilterPad flip_vulkan_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = &ff_vk_filter_config_output, - } -}; - const AVFilter ff_vf_hflip_vulkan = { .name = "hflip_vulkan", .description = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"), @@ -330,3 +339,31 @@ const AVFilter ff_vf_vflip_vulkan = { .priv_class = &vflip_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; + +static const AVOption flip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(flip_vulkan); + +static const AVFilterPad flip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &flip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +const AVFilter ff_vf_flip_vulkan = { + .name = "flip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Flip both horizontally and vertically"), + .priv_size = sizeof(FlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &flip_vulkan_uninit, + FILTER_INPUTS(flip_vulkan_inputs), + FILTER_OUTPUTS(flip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &flip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From bdc920574d79d83814b7cb7afc436114d85795fa Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 2 Dec 2021 11:08:58 +0100 Subject: [PATCH 337/894] Changelog: update with recent Vulkan filter additions --- Changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog b/Changelog index 9bdb51443b..13b22f6149 100644 --- a/Changelog +++ b/Changelog @@ -38,6 +38,8 @@ version : - support loongarch. - aspectralstats audio filter - adynamicsmooth audio filter +- libplacebo filter +- vflip_vulkan, hflip_vulkan and flip_vulkan filters version 4.4: From 4a6aece703e0084013a2da0c71e33c3131a0abe1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 10:24:59 +0100 Subject: [PATCH 338/894] fate/ffmpeg: Fix shortest tests The mpeg4 encoder is slice-threaded and its output depends upon the number of threads used. Therefore all tests of this encoder use a hardcoded number of threads (ENC_OPTS in fate-run.sh contains "-threads 1"; only the vsynth%-mpeg4-thread tests override this for the mpeg4 encoder, but they also use a hardcoded value to be consistent across different systems); only the new shortest and copy-shortest[12] (implicitly due to the sample used) tests don't and this leads to FATE-failures. Fix this by explicitly setting the thread count. Also switch the shortest test to framecrc, because hashing side data is itchy even though the side data used here (AV_PKT_DATA_QUALITY_STATS) has a defined endianness. Signed-off-by: Andreas Rheinhardt --- tests/fate/ffmpeg.mak | 4 +- tests/ref/fate/copy-shortest1 | 102 ++++++++-------- tests/ref/fate/copy-shortest2 | 102 ++++++++-------- tests/ref/fate/shortest | 220 +++++++++++++++++----------------- 4 files changed, 212 insertions(+), 216 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 8190eb974a..f9bc5bedf5 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -88,7 +88,7 @@ fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ FATE_FFMPEG-$(call ALLYES, SINE_FILTER AMIX_FILTER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-shortest fate-shortest: tests/data/vsynth_lena.yuv -fate-shortest: CMD = framemd5 -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -c:a ac3_fixed -shortest +fate-shortest: CMD = framecrc -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -threads 1 -c:v mpeg4 -c:a ac3_fixed -shortest FATE_STREAMCOPY-$(call ALLYES, EAC3_DEMUXER MOV_MUXER) += fate-copy-trac3074 fate-copy-trac3074: $(SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 @@ -140,7 +140,7 @@ tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ -f lavfi -i "sine=1000:d=1" \ - -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -c:a pcm_s16le -bitexact \ + -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -threads 1 -c:a pcm_s16le -bitexact \ -y $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut 2>/dev/null FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest1 diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1 index 6f5593fc15..69204b373a 100644 --- a/tests/ref/fate/copy-shortest1 +++ b/tests/ref/fate/copy-shortest1 @@ -1,7 +1,7 @@ #format: frame checksums #version: 2 #hash: MD5 -#extradata 0, 30, 226f0a640065a7bbc3a3e6dd5067de5a +#extradata 0, 30, 0e11a510b0c7831954402f81dd258188 #tb 0: 1/51200 #media_type 0: video #codec_id 0: mpeg4 @@ -15,110 +15,110 @@ #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 2048, 8876, b18b95893443cf5840d5962ad3456e97 +0, 0, 0, 2048, 8719, bbea2a7487d61d39a0b2f2fe62a4df4a 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 2048, 2048, 2048, 1025, 3c8f2dba6d80ebd4f656ecb772d46c9d +0, 2048, 2048, 2048, 975, 94f30e410595452ee981d96224516504 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 4096, 4096, 2048, 1226, 03470d542c38b78c48df45f19f2958e7 +0, 4096, 4096, 2048, 1167, d3b895191e8a06d19bbc8ac90e564b3b 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 6144, 6144, 2048, 1353, 51f123ef389e7ccb20d382ce779d81ed +0, 6144, 6144, 2048, 1274, 272f548f13dd6a45a5cd187f0e43e635 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 8192, 8192, 2048, 1421, 19897f392cc3517485bc6acfed2c2e2f +0, 8192, 8192, 2048, 1361, a0c67fc195fe867ae240dc8c48f85b2e 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 10240, 10240, 2048, 1446, 6d5a5dc31d09c144fba37c4e569f6e35 +0, 10240, 10240, 2048, 1415, f7a3746adb348eb00042b3eccff54a87 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 12288, 12288, 2048, 1483, 299f60d66033bab84ee737c6056e8588 +0, 12288, 12288, 2048, 1421, 8396b1c23f7d39f6f73c3469826317d6 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 14336, 14336, 2048, 1494, 54759f501f33744e81a456b5e4d695f7 +0, 14336, 14336, 2048, 1474, a9c493c020d710af7f2c98b9aae846ff 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 16384, 16384, 2048, 1552, 446661f8d2ee9b82c868cffb26160054 +0, 16384, 16384, 2048, 1467, b801d1a76c84923ab813e9a5d9ebdb78 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 18432, 18432, 2048, 1521, 0db5cd946c19b1552eacf56901558e5c +0, 18432, 18432, 2048, 1469, 22f7fcd055bf124436de9a9432f7c9d2 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 20480, 20480, 2048, 1545, 725ac20d7c171e448dce01d660021118 +0, 20480, 20480, 2048, 1506, da18f30d7008f2307ec51863a9873afd 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 22528, 22528, 2048, 1556, 429e63d26b4b3b95b91547489e49293d +0, 22528, 22528, 2048, 1520, 2c7d44ca3485373af6cfb3e44e495bf7 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 24576, 24576, 2048, 8659, fdf5109e322c9e5b80d9453a6ca4853d +0, 24576, 24576, 2048, 8524, 0634c69955cbffe94f4e15b288557cac 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 26624, 26624, 2048, 1144, 74ee1db0568ccf0c866189e59c8530cc +0, 26624, 26624, 2048, 1079, f081cbd559dab2b579f40d2fa988a959 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 28672, 28672, 2048, 1404, 9ddf9ceb0f25e54813f340c52b78a21f +0, 28672, 28672, 2048, 1343, fdf8069cd511f4fa185748118acfb72e 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 30720, 30720, 2048, 1550, 52ca630df0df5d29a3d4d0133e746d39 +0, 30720, 30720, 2048, 1486, e72dfcd069f5be3a30310002b1b5e252 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 32768, 32768, 2048, 1549, d999030e465c63639d2c501180ef9f63 +0, 32768, 32768, 2048, 1491, 710c5421d44a8c9356c1477cbcd27c0e 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 34816, 34816, 2048, 1582, 2ea6009ba8964412d0be2286296eb255 +0, 34816, 34816, 2048, 1504, 16a6d624b8175f1191ede25e2d588b92 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 36864, 36864, 2048, 1519, ba2c386a35843ce0bb25b4f5c17e2ee6 +0, 36864, 36864, 2048, 1481, 8696aa412629328687bda5e88dd40b81 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 38912, 38912, 2048, 1541, 34e3b4b5eb4ac0a0ab1fee2df6c38007 +0, 38912, 38912, 2048, 1521, 3c974bf799b8e35d295c6567ffeb7276 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 40960, 40960, 2048, 1578, f7c6d15a0de6088a1547d4be0898387f +0, 40960, 40960, 2048, 1514, 1a54ec5296f1551a7f67c515e40ca646 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 43008, 43008, 2048, 1622, e568e8b1bf951006f7d025890b950e5d +0, 43008, 43008, 2048, 1562, d285916a1c7a2fb9f37d18bfa977e075 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 45056, 45056, 2048, 1611, a208ef59b6f176a78d6c9113df17cf3d +0, 45056, 45056, 2048, 1562, 320c26adae1dad1741e02febdbd5b916 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 47104, 47104, 2048, 1706, f298b1930c927839470258f50d456dc8 +0, 47104, 47104, 2048, 1629, 60c6ebd71f641ebcff9997ee338d82bf 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 49152, 49152, 2048, 9737, 94e0e1fa27e7e57a956e0fc27670e5c8 +0, 49152, 49152, 2048, 9634, b72deda826b002179c46789e92c07978 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 51200, 51200, 2048, 1323, 248d92526f1e6a0d5e7592b40ac213c0 +0, 51200, 51200, 2048, 1239, 407105508656c920761e60c90540ee18 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 53248, 53248, 2048, 1621, 1ee6a5eb09be8ab281d05125c2868c56 +0, 53248, 53248, 2048, 1568, 1e5b232eaf9f35846ae25b881f658e5c 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 55296, 55296, 2048, 1698, db8b8ca03eca285d02dbce6eaaacdfd1 +0, 55296, 55296, 2048, 1641, f79725e348ed7796f2be7c153ce32580 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 57344, 57344, 2048, 1793, c50e4bdacb3ecef9c94be7b292929018 +0, 57344, 57344, 2048, 1735, ae14fbdbf8777d88077818db0ae346b3 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 59392, 59392, 2048, 1805, 1db64693c5ca5595b2f47097ffdfc612 +0, 59392, 59392, 2048, 1760, e943dc0f9ed56fbca1af43c3c3c6dea1 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 61440, 61440, 2048, 1880, 9f96e1bc1f3b595d6cd626dced55416f +0, 61440, 61440, 2048, 1798, efb1c91f9aee5c84c92e8cd5a5b58783 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 63488, 63488, 2048, 1902, 209393253d103d83d8dddde7fe044953 +0, 63488, 63488, 2048, 1830, 7aa74080b344e63280854570f701e2b8 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 65536, 65536, 2048, 1896, 9a845e06daafc1dd83d77fe507569968 +0, 65536, 65536, 2048, 1835, 566fa13f73b9aa63eed50511b112b191 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 67584, 67584, 2048, 1954, 77c37124c545198b688518508299f5f8 +0, 67584, 67584, 2048, 1902, 95933f1710291419d0febd37d5878362 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 69632, 69632, 2048, 1989, 0b142544ef59e421e33a40f9e685dffa +0, 69632, 69632, 2048, 1886, 5a8e4c7557ec0d09d40fbfabc5b92e63 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 71680, 71680, 2048, 2042, f69d73e0af0b4d9ef65205d8a0ee0937 +0, 71680, 71680, 2048, 1949, 3f81e2b8821c22f89501feafebb9d618 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 73728, 73728, 2048, 10838, bd02df61e3f5c0aa572904220aaf04a6 +0, 73728, 73728, 2048, 10776, 29e4a6fdc625965feae7faa8ab239db1 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 75776, 75776, 2048, 1511, 6ab5a58771e346bd8756fdd68139ad8e +0, 75776, 75776, 2048, 1413, 4b5bde19c84eca2c776f6ac45163a0a5 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 77824, 77824, 2048, 1780, 62e0bc487aa55ad381d0a1e7f8b7a477 +0, 77824, 77824, 2048, 1731, 7f46b3e146e52fd500dbf53a3c744662 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 79872, 79872, 2048, 1953, ad1854098648e499e347cf828202d1d5 +0, 79872, 79872, 2048, 1888, 2bd4182a0fe98db2990c8e39c0500872 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 81920, 81920, 2048, 2036, da8405d19586da34274a578f4972fd7f +0, 81920, 81920, 2048, 1989, f3bf07391ef46cba98eb78fdc3707fa3 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 83968, 83968, 2048, 1980, e046fca4a3652fad1b0b22e49a290dd8 +0, 83968, 83968, 2048, 1949, 0650751332acc5d5f96f292ffc4add21 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 86016, 86016, 2048, 2014, 01806ec06d4cdb2b840a6f7993b648e3 +0, 86016, 86016, 2048, 1956, d52d57b697f4ec90bb1f69fd7ece1952 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 88064, 88064, 2048, 2040, 19c5cc70489711d467ef7ef4414fdf6a +0, 88064, 88064, 2048, 2012, e25c0bb0ec726fe5c9ade88cf7ae9a19 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 90112, 90112, 2048, 2071, 2bc9f2d22ac276366337341e89efd6cb +0, 90112, 90112, 2048, 1995, eb0377542bc15580ef8f772ce6f506bd 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 92160, 92160, 2048, 2117, 7173333f3ff643752b8afea6d5486117 +0, 92160, 92160, 2048, 2078, 7aa93cd366118984932da377f4743de6 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 94208, 94208, 2048, 2169, fda9c958dc9fea54efa935624528a902 +0, 94208, 94208, 2048, 2116, 9d8c672e97c27ed4e3281bb10481914a 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 96256, 96256, 2048, 2096, 9516005a46f05f1a582524be91c4d672 +0, 96256, 96256, 2048, 2024, 18d42dbec2fa24fd30374d79a054cd4f 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 98304, 98304, 2048, 11219, 834f992165c0ee5e5a60fff78610b449 +0, 98304, 98304, 2048, 11182, e35a2ab846029effdbca0e43639717f2 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 100352, 100352, 2048, 1506, 74f01869f22e72e244f31e2da2614676 +0, 100352, 100352, 2048, 1423, f480272c7d0b97834bc8ea36cceca61d 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2 index 6f5593fc15..69204b373a 100644 --- a/tests/ref/fate/copy-shortest2 +++ b/tests/ref/fate/copy-shortest2 @@ -1,7 +1,7 @@ #format: frame checksums #version: 2 #hash: MD5 -#extradata 0, 30, 226f0a640065a7bbc3a3e6dd5067de5a +#extradata 0, 30, 0e11a510b0c7831954402f81dd258188 #tb 0: 1/51200 #media_type 0: video #codec_id 0: mpeg4 @@ -15,110 +15,110 @@ #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 2048, 8876, b18b95893443cf5840d5962ad3456e97 +0, 0, 0, 2048, 8719, bbea2a7487d61d39a0b2f2fe62a4df4a 1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 2048, 2048, 2048, 1025, 3c8f2dba6d80ebd4f656ecb772d46c9d +0, 2048, 2048, 2048, 975, 94f30e410595452ee981d96224516504 1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 4096, 4096, 2048, 1226, 03470d542c38b78c48df45f19f2958e7 +0, 4096, 4096, 2048, 1167, d3b895191e8a06d19bbc8ac90e564b3b 1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 6144, 6144, 2048, 1353, 51f123ef389e7ccb20d382ce779d81ed +0, 6144, 6144, 2048, 1274, 272f548f13dd6a45a5cd187f0e43e635 1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 8192, 8192, 2048, 1421, 19897f392cc3517485bc6acfed2c2e2f +0, 8192, 8192, 2048, 1361, a0c67fc195fe867ae240dc8c48f85b2e 1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 10240, 10240, 2048, 1446, 6d5a5dc31d09c144fba37c4e569f6e35 +0, 10240, 10240, 2048, 1415, f7a3746adb348eb00042b3eccff54a87 1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 12288, 12288, 2048, 1483, 299f60d66033bab84ee737c6056e8588 +0, 12288, 12288, 2048, 1421, 8396b1c23f7d39f6f73c3469826317d6 1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 14336, 14336, 2048, 1494, 54759f501f33744e81a456b5e4d695f7 +0, 14336, 14336, 2048, 1474, a9c493c020d710af7f2c98b9aae846ff 1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 16384, 16384, 2048, 1552, 446661f8d2ee9b82c868cffb26160054 +0, 16384, 16384, 2048, 1467, b801d1a76c84923ab813e9a5d9ebdb78 1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 18432, 18432, 2048, 1521, 0db5cd946c19b1552eacf56901558e5c +0, 18432, 18432, 2048, 1469, 22f7fcd055bf124436de9a9432f7c9d2 1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 20480, 20480, 2048, 1545, 725ac20d7c171e448dce01d660021118 +0, 20480, 20480, 2048, 1506, da18f30d7008f2307ec51863a9873afd 1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 22528, 22528, 2048, 1556, 429e63d26b4b3b95b91547489e49293d +0, 22528, 22528, 2048, 1520, 2c7d44ca3485373af6cfb3e44e495bf7 1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 24576, 24576, 2048, 8659, fdf5109e322c9e5b80d9453a6ca4853d +0, 24576, 24576, 2048, 8524, 0634c69955cbffe94f4e15b288557cac 1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb 1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 26624, 26624, 2048, 1144, 74ee1db0568ccf0c866189e59c8530cc +0, 26624, 26624, 2048, 1079, f081cbd559dab2b579f40d2fa988a959 1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 28672, 28672, 2048, 1404, 9ddf9ceb0f25e54813f340c52b78a21f +0, 28672, 28672, 2048, 1343, fdf8069cd511f4fa185748118acfb72e 1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 30720, 30720, 2048, 1550, 52ca630df0df5d29a3d4d0133e746d39 +0, 30720, 30720, 2048, 1486, e72dfcd069f5be3a30310002b1b5e252 1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 32768, 32768, 2048, 1549, d999030e465c63639d2c501180ef9f63 +0, 32768, 32768, 2048, 1491, 710c5421d44a8c9356c1477cbcd27c0e 1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 34816, 34816, 2048, 1582, 2ea6009ba8964412d0be2286296eb255 +0, 34816, 34816, 2048, 1504, 16a6d624b8175f1191ede25e2d588b92 1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 36864, 36864, 2048, 1519, ba2c386a35843ce0bb25b4f5c17e2ee6 +0, 36864, 36864, 2048, 1481, 8696aa412629328687bda5e88dd40b81 1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 38912, 38912, 2048, 1541, 34e3b4b5eb4ac0a0ab1fee2df6c38007 +0, 38912, 38912, 2048, 1521, 3c974bf799b8e35d295c6567ffeb7276 1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b 1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 40960, 40960, 2048, 1578, f7c6d15a0de6088a1547d4be0898387f +0, 40960, 40960, 2048, 1514, 1a54ec5296f1551a7f67c515e40ca646 1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 43008, 43008, 2048, 1622, e568e8b1bf951006f7d025890b950e5d +0, 43008, 43008, 2048, 1562, d285916a1c7a2fb9f37d18bfa977e075 1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 45056, 45056, 2048, 1611, a208ef59b6f176a78d6c9113df17cf3d +0, 45056, 45056, 2048, 1562, 320c26adae1dad1741e02febdbd5b916 1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 47104, 47104, 2048, 1706, f298b1930c927839470258f50d456dc8 +0, 47104, 47104, 2048, 1629, 60c6ebd71f641ebcff9997ee338d82bf 1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 49152, 49152, 2048, 9737, 94e0e1fa27e7e57a956e0fc27670e5c8 +0, 49152, 49152, 2048, 9634, b72deda826b002179c46789e92c07978 1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 51200, 51200, 2048, 1323, 248d92526f1e6a0d5e7592b40ac213c0 +0, 51200, 51200, 2048, 1239, 407105508656c920761e60c90540ee18 1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 53248, 53248, 2048, 1621, 1ee6a5eb09be8ab281d05125c2868c56 +0, 53248, 53248, 2048, 1568, 1e5b232eaf9f35846ae25b881f658e5c 1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 55296, 55296, 2048, 1698, db8b8ca03eca285d02dbce6eaaacdfd1 +0, 55296, 55296, 2048, 1641, f79725e348ed7796f2be7c153ce32580 1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 57344, 57344, 2048, 1793, c50e4bdacb3ecef9c94be7b292929018 +0, 57344, 57344, 2048, 1735, ae14fbdbf8777d88077818db0ae346b3 1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 59392, 59392, 2048, 1805, 1db64693c5ca5595b2f47097ffdfc612 +0, 59392, 59392, 2048, 1760, e943dc0f9ed56fbca1af43c3c3c6dea1 1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 61440, 61440, 2048, 1880, 9f96e1bc1f3b595d6cd626dced55416f +0, 61440, 61440, 2048, 1798, efb1c91f9aee5c84c92e8cd5a5b58783 1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 63488, 63488, 2048, 1902, 209393253d103d83d8dddde7fe044953 +0, 63488, 63488, 2048, 1830, 7aa74080b344e63280854570f701e2b8 1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 65536, 65536, 2048, 1896, 9a845e06daafc1dd83d77fe507569968 +0, 65536, 65536, 2048, 1835, 566fa13f73b9aa63eed50511b112b191 1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a 1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 67584, 67584, 2048, 1954, 77c37124c545198b688518508299f5f8 +0, 67584, 67584, 2048, 1902, 95933f1710291419d0febd37d5878362 1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 69632, 69632, 2048, 1989, 0b142544ef59e421e33a40f9e685dffa +0, 69632, 69632, 2048, 1886, 5a8e4c7557ec0d09d40fbfabc5b92e63 1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 71680, 71680, 2048, 2042, f69d73e0af0b4d9ef65205d8a0ee0937 +0, 71680, 71680, 2048, 1949, 3f81e2b8821c22f89501feafebb9d618 1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 73728, 73728, 2048, 10838, bd02df61e3f5c0aa572904220aaf04a6 +0, 73728, 73728, 2048, 10776, 29e4a6fdc625965feae7faa8ab239db1 1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 75776, 75776, 2048, 1511, 6ab5a58771e346bd8756fdd68139ad8e +0, 75776, 75776, 2048, 1413, 4b5bde19c84eca2c776f6ac45163a0a5 1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 77824, 77824, 2048, 1780, 62e0bc487aa55ad381d0a1e7f8b7a477 +0, 77824, 77824, 2048, 1731, 7f46b3e146e52fd500dbf53a3c744662 1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 79872, 79872, 2048, 1953, ad1854098648e499e347cf828202d1d5 +0, 79872, 79872, 2048, 1888, 2bd4182a0fe98db2990c8e39c0500872 1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d 1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 81920, 81920, 2048, 2036, da8405d19586da34274a578f4972fd7f +0, 81920, 81920, 2048, 1989, f3bf07391ef46cba98eb78fdc3707fa3 1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 83968, 83968, 2048, 1980, e046fca4a3652fad1b0b22e49a290dd8 +0, 83968, 83968, 2048, 1949, 0650751332acc5d5f96f292ffc4add21 1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 86016, 86016, 2048, 2014, 01806ec06d4cdb2b840a6f7993b648e3 +0, 86016, 86016, 2048, 1956, d52d57b697f4ec90bb1f69fd7ece1952 1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 88064, 88064, 2048, 2040, 19c5cc70489711d467ef7ef4414fdf6a +0, 88064, 88064, 2048, 2012, e25c0bb0ec726fe5c9ade88cf7ae9a19 1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 90112, 90112, 2048, 2071, 2bc9f2d22ac276366337341e89efd6cb +0, 90112, 90112, 2048, 1995, eb0377542bc15580ef8f772ce6f506bd 1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 92160, 92160, 2048, 2117, 7173333f3ff643752b8afea6d5486117 +0, 92160, 92160, 2048, 2078, 7aa93cd366118984932da377f4743de6 1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 94208, 94208, 2048, 2169, fda9c958dc9fea54efa935624528a902 +0, 94208, 94208, 2048, 2116, 9d8c672e97c27ed4e3281bb10481914a 1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 96256, 96256, 2048, 2096, 9516005a46f05f1a582524be91c4d672 +0, 96256, 96256, 2048, 2024, 18d42dbec2fa24fd30374d79a054cd4f 1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 98304, 98304, 2048, 11219, 834f992165c0ee5e5a60fff78610b449 +0, 98304, 98304, 2048, 11182, e35a2ab846029effdbca0e43639717f2 1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 100352, 100352, 2048, 1506, 74f01869f22e72e244f31e2da2614676 +0, 100352, 100352, 2048, 1423, f480272c7d0b97834bc8ea36cceca61d 1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/shortest b/tests/ref/fate/shortest index d264955389..64b5bed312 100644 --- a/tests/ref/fate/shortest +++ b/tests/ref/fate/shortest @@ -1,6 +1,3 @@ -#format: frame checksums -#version: 2 -#hash: MD5 #tb 0: 1/25 #media_type 0: video #codec_id 0: mpeg4 @@ -12,112 +9,111 @@ #sample_rate 1: 44100 #channel_layout 1: 4 #channel_layout_name 1: mono -#stream#, dts, pts, duration, size, hash -1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce -0, 0, 0, 1, 8906, dc889f5692ac7d91295c9fbae76a9818, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb -1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 -0, 1, 1, 1, 1025, 3c8f2dba6d80ebd4f656ecb772d46c9d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 -0, 2, 2, 1, 1226, 03470d542c38b78c48df45f19f2958e7, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade -0, 3, 3, 1, 1353, 51f123ef389e7ccb20d382ce779d81ed, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 -0, 4, 4, 1, 1421, 19897f392cc3517485bc6acfed2c2e2f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 -0, 5, 5, 1, 1446, 6d5a5dc31d09c144fba37c4e569f6e35, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 -1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 -0, 6, 6, 1, 1483, 299f60d66033bab84ee737c6056e8588, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 -0, 7, 7, 1, 1494, 54759f501f33744e81a456b5e4d695f7, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 -0, 8, 8, 1, 1552, 446661f8d2ee9b82c868cffb26160054, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae -0, 9, 9, 1, 1521, 0db5cd946c19b1552eacf56901558e5c, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 -0, 10, 10, 1, 1545, 725ac20d7c171e448dce01d660021118, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 -0, 11, 11, 1, 1556, 429e63d26b4b3b95b91547489e49293d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c -0, 12, 12, 1, 8689, 710c00d071339e873215f0c8b58cab0b, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb -1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb -1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 -0, 13, 13, 1, 1144, 74ee1db0568ccf0c866189e59c8530cc, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 -0, 14, 14, 1, 1404, 9ddf9ceb0f25e54813f340c52b78a21f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 -0, 15, 15, 1, 1550, 52ca630df0df5d29a3d4d0133e746d39, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc -0, 16, 16, 1, 1549, d999030e465c63639d2c501180ef9f63, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 -0, 17, 17, 1, 1582, 2ea6009ba8964412d0be2286296eb255, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 -0, 18, 18, 1, 1519, ba2c386a35843ce0bb25b4f5c17e2ee6, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb -0, 19, 19, 1, 1541, 34e3b4b5eb4ac0a0ab1fee2df6c38007, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b -1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 -0, 20, 20, 1, 1578, f7c6d15a0de6088a1547d4be0898387f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d -0, 21, 21, 1, 1622, e568e8b1bf951006f7d025890b950e5d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 -0, 22, 22, 1, 1611, a208ef59b6f176a78d6c9113df17cf3d, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae -0, 23, 23, 1, 1706, f298b1930c927839470258f50d456dc8, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed -0, 24, 24, 1, 9767, 9a4cf29909201c67bf40238efdf65d19, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb -1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd -0, 25, 25, 1, 1323, 248d92526f1e6a0d5e7592b40ac213c0, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 -1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 -0, 26, 26, 1, 1621, 1ee6a5eb09be8ab281d05125c2868c56, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 -0, 27, 27, 1, 1698, db8b8ca03eca285d02dbce6eaaacdfd1, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca -0, 28, 28, 1, 1793, c50e4bdacb3ecef9c94be7b292929018, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 -0, 29, 29, 1, 1805, 1db64693c5ca5595b2f47097ffdfc612, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 -0, 30, 30, 1, 1880, 9f96e1bc1f3b595d6cd626dced55416f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 -0, 31, 31, 1, 1902, 209393253d103d83d8dddde7fe044953, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab -0, 32, 32, 1, 1896, 9a845e06daafc1dd83d77fe507569968, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a -1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c -0, 33, 33, 1, 1954, 77c37124c545198b688518508299f5f8, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f -0, 34, 34, 1, 1989, 0b142544ef59e421e33a40f9e685dffa, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 -0, 35, 35, 1, 2042, f69d73e0af0b4d9ef65205d8a0ee0937, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 -0, 36, 36, 1, 10868, 2f4b959d1dc05a1d7e00cbe204b5fc2d, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb -1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 -0, 37, 37, 1, 1511, 6ab5a58771e346bd8756fdd68139ad8e, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 -0, 38, 38, 1, 1780, 62e0bc487aa55ad381d0a1e7f8b7a477, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e -0, 39, 39, 1, 1953, ad1854098648e499e347cf828202d1d5, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d -1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 -0, 40, 40, 1, 2036, da8405d19586da34274a578f4972fd7f, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 -0, 41, 41, 1, 1980, e046fca4a3652fad1b0b22e49a290dd8, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb -0, 42, 42, 1, 2014, 01806ec06d4cdb2b840a6f7993b648e3, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 -0, 43, 43, 1, 2040, 19c5cc70489711d467ef7ef4414fdf6a, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b -0, 44, 44, 1, 2071, 2bc9f2d22ac276366337341e89efd6cb, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 -0, 45, 45, 1, 2117, 7173333f3ff643752b8afea6d5486117, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 -0, 46, 46, 1, 2169, fda9c958dc9fea54efa935624528a902, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 -1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 -0, 47, 47, 1, 2096, 9516005a46f05f1a582524be91c4d672, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 -0, 48, 48, 1, 11249, 36825ee3b6f996a93b1031bd1106586a, S=1, 8, 438432f07a4fcc01dd57de0bf46d9acb -1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af -0, 49, 49, 1, 1506, 74f01869f22e72e244f31e2da2614676, S=1, 8, f6ebfc548ad9ba3d00b655047277212d -1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d +1, -256, -256, 1536, 416, 0xef8ccbe3 +0, 0, 0, 1, 8749, 0x57039d10, S=1, 8 +1, 1280, 1280, 1536, 418, 0xa0ccc09d +0, 1, 1, 1, 975, 0x2fcf0617, F=0x0, S=1, 8 +1, 2816, 2816, 1536, 418, 0xb873cb60 +0, 2, 2, 1, 1167, 0x6d32482b, F=0x0, S=1, 8 +1, 4352, 4352, 1536, 418, 0x1366c008 +0, 3, 3, 1, 1274, 0xab1d80c9, F=0x0, S=1, 8 +1, 5888, 5888, 1536, 418, 0xeb24c8da +0, 4, 4, 1, 1361, 0x9dc28a69, F=0x0, S=1, 8 +1, 7424, 7424, 1536, 418, 0xc75ac55e +0, 5, 5, 1, 1415, 0x41d8ba3e, F=0x0, S=1, 8 +1, 8960, 8960, 1536, 418, 0xe336d28d +1, 10496, 10496, 1536, 418, 0xd0acc452 +0, 6, 6, 1, 1421, 0x8c83ad35, F=0x0, S=1, 8 +1, 12032, 12032, 1536, 418, 0xae88c75f +0, 7, 7, 1, 1474, 0x1025b9b0, F=0x0, S=1, 8 +1, 13568, 13568, 1536, 418, 0xa200b8f0 +0, 8, 8, 1, 1467, 0xf3c0c714, F=0x0, S=1, 8 +1, 15104, 15104, 1536, 418, 0xbbf9cd36 +0, 9, 9, 1, 1469, 0x1b9faf72, F=0x0, S=1, 8 +1, 16640, 16640, 1536, 418, 0x585ec129 +0, 10, 10, 1, 1506, 0x18a9c359, F=0x0, S=1, 8 +1, 18176, 18176, 1536, 418, 0xda1acf75 +0, 11, 11, 1, 1520, 0x0ec1d39a, F=0x0, S=1, 8 +1, 19712, 19712, 1536, 418, 0x9bb2cfeb +0, 12, 12, 1, 8554, 0xfab776e0, S=1, 8 +1, 21248, 21248, 1536, 418, 0x83f2bf72 +1, 22784, 22784, 1536, 418, 0xdb4dcbe8 +0, 13, 13, 1, 1079, 0x13e40cb3, F=0x0, S=1, 8 +1, 24320, 24320, 1536, 418, 0x6813cefa +0, 14, 14, 1, 1343, 0xf0058d2e, F=0x0, S=1, 8 +1, 25856, 25856, 1536, 418, 0x3573d3c5 +0, 15, 15, 1, 1486, 0x1da1c64e, F=0x0, S=1, 8 +1, 27392, 27392, 1536, 418, 0x80c4c8d2 +0, 16, 16, 1, 1491, 0x872dd43d, F=0x0, S=1, 8 +1, 28928, 28928, 1536, 418, 0xaeaac123 +0, 17, 17, 1, 1504, 0x5907c6ca, F=0x0, S=1, 8 +1, 30464, 30464, 1536, 418, 0xe2c9c038 +0, 18, 18, 1, 1481, 0xde66ba0a, F=0x0, S=1, 8 +1, 32000, 32000, 1536, 418, 0x3f37c65b +0, 19, 19, 1, 1521, 0xf46dcef9, F=0x0, S=1, 8 +1, 33536, 33536, 1536, 418, 0xd8e3d1f3 +1, 35072, 35072, 1536, 418, 0x34bdcb46 +0, 20, 20, 1, 1514, 0x001ed7b1, F=0x0, S=1, 8 +1, 36608, 36608, 1536, 418, 0x4e92be94 +0, 21, 21, 1, 1562, 0x3974e095, F=0x0, S=1, 8 +1, 38144, 38144, 1536, 418, 0xa9d8c8d0 +0, 22, 22, 1, 1562, 0xa94bf1fc, F=0x0, S=1, 8 +1, 39680, 39680, 1536, 418, 0xe4c8bc20 +0, 23, 23, 1, 1629, 0xdfcc0234, F=0x0, S=1, 8 +1, 41216, 41216, 1536, 418, 0x2ccac571 +0, 24, 24, 1, 9664, 0xbf319bb0, S=1, 8 +1, 42752, 42752, 1536, 418, 0xd2a0cbff +0, 25, 25, 1, 1239, 0x1f9662f7, F=0x0, S=1, 8 +1, 44288, 44288, 1536, 418, 0xffadb489 +1, 45824, 45824, 1536, 418, 0x1246cae7 +0, 26, 26, 1, 1568, 0xfbf8ed9d, F=0x0, S=1, 8 +1, 47360, 47360, 1536, 418, 0xa74eb1f7 +0, 27, 27, 1, 1641, 0x46aafde5, F=0x0, S=1, 8 +1, 48896, 48896, 1536, 418, 0x98cfc032 +0, 28, 28, 1, 1735, 0xa9363e9b, F=0x0, S=1, 8 +1, 50432, 50432, 1536, 418, 0x42d6c12e +0, 29, 29, 1, 1760, 0x99b82cbc, F=0x0, S=1, 8 +1, 51968, 51968, 1536, 418, 0x2180c196 +0, 30, 30, 1, 1798, 0xc0ba5286, F=0x0, S=1, 8 +1, 53504, 53504, 1536, 418, 0x35f2b4d1 +0, 31, 31, 1, 1830, 0x4e8b4b80, F=0x0, S=1, 8 +1, 55040, 55040, 1536, 418, 0x7b5fc73a +0, 32, 32, 1, 1835, 0x218a69cb, F=0x0, S=1, 8 +1, 56576, 56576, 1536, 418, 0xbccebddd +1, 58112, 58112, 1536, 418, 0x40a1bcc7 +0, 33, 33, 1, 1902, 0x8f2b67d2, F=0x0, S=1, 8 +1, 59648, 59648, 1536, 418, 0xbcafbf6e +0, 34, 34, 1, 1886, 0xf4087481, F=0x0, S=1, 8 +1, 61184, 61184, 1536, 418, 0xb8e4b630 +0, 35, 35, 1, 1949, 0x142c8ac1, F=0x0, S=1, 8 +1, 62720, 62720, 1536, 418, 0xc667bd39 +0, 36, 36, 1, 10806, 0x603680c3, S=1, 8 +1, 64256, 64256, 1536, 418, 0x2985c4ac +0, 37, 37, 1, 1413, 0xc52395a2, F=0x0, S=1, 8 +1, 65792, 65792, 1536, 418, 0xb229b697 +0, 38, 38, 1, 1731, 0xa26a2fb2, F=0x0, S=1, 8 +1, 67328, 67328, 1536, 418, 0xd2eec6d8 +0, 39, 39, 1, 1888, 0xa2995d2a, F=0x0, S=1, 8 +1, 68864, 68864, 1536, 418, 0x74a9c1a9 +1, 70400, 70400, 1536, 418, 0x2d1cc383 +0, 40, 40, 1, 1989, 0x0274904a, F=0x0, S=1, 8 +1, 71936, 71936, 1536, 418, 0x0ad9c88a +0, 41, 41, 1, 1949, 0x66fa8de9, F=0x0, S=1, 8 +1, 73472, 73472, 1536, 418, 0x57accd5f +0, 42, 42, 1, 1956, 0x4e2e831d, F=0x0, S=1, 8 +1, 75008, 75008, 1536, 416, 0x99f5b2b6 +0, 43, 43, 1, 2012, 0x1d75ac7a, F=0x0, S=1, 8 +1, 76544, 76544, 1536, 418, 0xe60fc1af +0, 44, 44, 1, 1995, 0xdc478fec, F=0x0, S=1, 8 +1, 78080, 78080, 1536, 418, 0xebc8c568 +0, 45, 45, 1, 2078, 0x416aaf11, F=0x0, S=1, 8 +1, 79616, 79616, 1536, 418, 0x7361c949 +0, 46, 46, 1, 2116, 0x1416cc81, F=0x0, S=1, 8 +1, 81152, 81152, 1536, 418, 0xebb4bde9 +1, 82688, 82688, 1536, 418, 0x72e8bad1 +0, 47, 47, 1, 2024, 0xf1c1ad7d, F=0x0, S=1, 8 +1, 84224, 84224, 1536, 418, 0xb479b641 +0, 48, 48, 1, 11212, 0xc61a3f0a, S=1, 8 +1, 85760, 85760, 1536, 418, 0xae06ca91 +0, 49, 49, 1, 1423, 0x45fba9e4, F=0x0, S=1, 8 +1, 87296, 87296, 1536, 418, 0x7bdcc3c7 From b94db16bf5d24e2520bb1209d13b8c8f0b09b230 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 15:31:49 +0100 Subject: [PATCH 339/894] fate/ffmpeg: Fix requirements of shortest tests Fixes FATE failures if e.g. libavdevice is disabled. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- tests/fate/ffmpeg.mak | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index f9bc5bedf5..4ba73a8dfa 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -86,7 +86,11 @@ fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ -guess_layout_max 0 -f s32le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) \ -f ac3 -flags +bitexact -c ac3_fixed -FATE_FFMPEG-$(call ALLYES, SINE_FILTER AMIX_FILTER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-shortest +FATE_FFMPEG-$(call ALLYES, FILE_PROTOCOL LAVFI_INDEV RAWVIDEO_DEMUXER \ + SINE_FILTER PCM_S16LE_DECODER RAWVIDEO_DECODER \ + ARESAMPLE_FILTER AMIX_FILTER MPEG4_ENCODER \ + AC3_FIXED_ENCODER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-shortest fate-shortest: tests/data/vsynth_lena.yuv fate-shortest: CMD = framecrc -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -threads 1 -c:v mpeg4 -c:a ac3_fixed -shortest @@ -143,11 +147,21 @@ tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -threads 1 -c:a pcm_s16le -bitexact \ -y $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut 2>/dev/null -FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest1 +FATE_STREAMCOPY-$(call ALLYES, FILE_PROTOCOL RAWVIDEO_DEMUXER LAVFI_INDEV \ + RAWVIDEO_DECODER PCM_S16LE_DECODER MPEG4_ENCODER \ + PCM_S16LE_ENCODER SINE_FILTER NUT_DEMUXER \ + MPEG4_DECODER ARESAMPLE_FILTER AMIX_FILTER \ + NUT_MUXER AC3_FIXED_ENCODER PIPE_PROTOCOL) \ + += fate-copy-shortest1 fate-copy-shortest1: tests/data/audio_shorter_than_video.nut fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -fflags +bitexact -flags +bitexact -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -fflags +bitexact -flags +bitexact -c:v copy -c:a ac3_fixed -shortest -FATE_STREAMCOPY-$(call ALLYES, SINE_FILTER AMIX_FILTER NUT_MUXER PCM_S16LE_ENCODER MPEG4_ENCODER AC3_FIXED_ENCODER) += fate-copy-shortest2 +FATE_STREAMCOPY-$(call ALLYES, FILE_PROTOCOL RAWVIDEO_DEMUXER LAVFI_INDEV \ + RAWVIDEO_DECODER PCM_S16LE_DECODER MPEG4_ENCODER \ + PCM_S16LE_ENCODER SINE_FILTER NUT_DEMUXER \ + MPEG4_DECODER ARESAMPLE_FILTER AMIX_FILTER \ + NUT_MUXER AC3_FIXED_ENCODER PIPE_PROTOCOL) \ + += fate-copy-shortest2 fate-copy-shortest2: tests/data/audio_shorter_than_video.nut fate-copy-shortest2: CMD = framemd5 -auto_conversion_filters -fflags +bitexact -flags +bitexact -f lavfi -i "sine=3000:d=10" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 1:v:0 -map "[audio]" -fflags +bitexact -flags +bitexact -c:v copy -c:a ac3_fixed -shortest From 4a90c039e7a17c913d2961f902f667d38490b6ab Mon Sep 17 00:00:00 2001 From: John-Paul Stewart Date: Sat, 27 Nov 2021 16:45:50 -0500 Subject: [PATCH 340/894] avformat/mvdec: fix reading number of audio channels The number of audio channels is stored after the magic number identifying the audio format. Prior to this patch the code has been reading it earlier, causing files with only one audio channel to be handled incorrectly. Reviewed-by: Peter Ross --- libavformat/mvdec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index d58281c3a9..8492928820 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -340,8 +340,8 @@ static int mv_read_header(AVFormatContext *avctx) return AVERROR_INVALIDDATA; } avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - if (set_channels(avctx, ast, avio_rb32(pb)) < 0) - return AVERROR_INVALIDDATA; + + avio_skip(pb, 4); v = avio_rb32(pb); if (v == AUDIO_FORMAT_SIGNED) { @@ -350,7 +350,11 @@ static int mv_read_header(AVFormatContext *avctx) avpriv_request_sample(avctx, "Audio compression (format %i)", v); } - avio_skip(pb, 12); + if (set_channels(avctx, ast, avio_rb32(pb)) < 0) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 8); + var_read_metadata(avctx, "title", 0x80); var_read_metadata(avctx, "comment", 0x100); avio_skip(pb, 0x80); From 6c76b6392348460472f0b6deac4d0a161109d498 Mon Sep 17 00:00:00 2001 From: John-Paul Stewart Date: Sat, 27 Nov 2021 16:45:51 -0500 Subject: [PATCH 341/894] avformat/mvdec: handle audio sample size Adds support for reading audio sample size from the data instead of assuming all audio is 16 bits per sample. Reviewed-by: Peter Ross --- libavformat/mvdec.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 8492928820..8b54a9ab04 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -299,6 +299,8 @@ static int mv_read_header(AVFormatContext *avctx) if (version == 2) { uint64_t timestamp; int v; + uint32_t bytes_per_sample; + avio_skip(pb, 22); /* allocate audio track first to prevent unnecessary seeking @@ -341,11 +343,21 @@ static int mv_read_header(AVFormatContext *avctx) } avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - avio_skip(pb, 4); + bytes_per_sample = avio_rb32(pb); v = avio_rb32(pb); if (v == AUDIO_FORMAT_SIGNED) { - ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; + switch (bytes_per_sample) { + case 1: + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S8; + break; + case 2: + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; + break; + default: + avpriv_request_sample(avctx, "Audio sample size %i bytes", bytes_per_sample); + break; + } } else { avpriv_request_sample(avctx, "Audio compression (format %i)", v); } @@ -369,7 +381,7 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 8); av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codecpar->channels * 2LL); + timestamp += asize / (ast->codecpar->channels * bytes_per_sample); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); From 77a37e0369b4b0adf06ccbda2f95828fb6afb2c3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 12:24:10 +0100 Subject: [PATCH 342/894] swresample/swresample: Remove array size hint from swr_convert() SWR_CH_MAX is internal only and the arrays are therefore not required to have that many elements (and they typically don't do it). So remove this potentially confusing hint. (Newer versions of GCC emit -Warray-parameter= warnings for this, because the definition with explicit size differs from the declaration (which leaves the size unspecified); this is IMO a false-positive, because definition and declaration didn't conflict, but anyway it is fixed by this commit.) Signed-off-by: Andreas Rheinhardt --- libswresample/swresample.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 22c2c33673..c03fe5528f 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -711,8 +711,10 @@ int swr_is_initialized(struct SwrContext *s) { return !!s->in_buffer.ch_count; } -int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, - const uint8_t *in_arg [SWR_CH_MAX], int in_count){ +int attribute_align_arg swr_convert(struct SwrContext *s, + uint8_t **out_arg, int out_count, + const uint8_t **in_arg, int in_count) +{ AudioData * in= &s->in; AudioData *out= &s->out; int av_unused max_output; From 05c924a86db04e05831876dd2720093dcc2dc8e1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 16:00:16 +0100 Subject: [PATCH 343/894] avdevice/lavfi: Cleanup generically on read_header failure Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 4eb1f56f7d..826dafbd00 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -356,8 +356,6 @@ end: av_free(pix_fmts); avfilter_inout_free(&input_links); avfilter_inout_free(&output_links); - if (ret < 0) - lavfi_read_close(avctx); return ret; } @@ -507,4 +505,5 @@ const AVInputFormat ff_lavfi_demuxer = { .read_close = lavfi_read_close, .flags = AVFMT_NOFILE, .priv_class = &lavfi_class, + .flags_internal = FF_FMT_INIT_CLEANUP, }; From 531d289cfd853567df69d5eb490425677e3759b9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 16:41:09 +0100 Subject: [PATCH 344/894] avdevice/lavfi: Properly free an AVDictionary It is not documented that freeing the last (and only) entry of an AVDictionary frees the dictionary. Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 826dafbd00..d9083ad984 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -150,7 +150,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) if (avctx->protocol_whitelist && (ret = av_dict_set(&options, "protocol_whitelist", avctx->protocol_whitelist, 0)) < 0) goto end; ret = avio_open2(&avio, lavfi->graph_filename, AVIO_FLAG_READ, &avctx->interrupt_callback, &options); - av_dict_set(&options, "protocol_whitelist", NULL, 0); + av_dict_free(&options); if (ret < 0) goto end; av_bprint_init(&graph_file_pb, 0, AV_BPRINT_SIZE_UNLIMITED); From 5e7bdbfff6b99ea61254b048605aca3cb349ddb1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 18:16:17 +0100 Subject: [PATCH 345/894] avcodec/h264_redundant_pps_bsf: Remove flush callback extradata_pic_init_qp is unset since fa75e438756f159a667080dcba58ea2e3b190001 (and resetting current_pic_init_qp to the value it had in extradata never made much sense). Signed-off-by: Andreas Rheinhardt --- libavcodec/h264_redundant_pps_bsf.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index fb678beef3..4b2831fb04 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -33,7 +33,6 @@ typedef struct H264RedundantPPSContext { int global_pic_init_qp; int current_pic_init_qp; - int extradata_pic_init_qp; } H264RedundantPPSContext; @@ -111,12 +110,6 @@ static int h264_redundant_pps_update_fragment(AVBSFContext *bsf, return 0; } -static void h264_redundant_pps_flush(AVBSFContext *bsf) -{ - H264RedundantPPSContext *ctx = bsf->priv_data; - ctx->current_pic_init_qp = ctx->extradata_pic_init_qp; -} - static const CBSBSFType h264_redundant_pps_type = { .codec_id = AV_CODEC_ID_H264, .fragment_name = "access unit", @@ -141,7 +134,6 @@ const AVBitStreamFilter ff_h264_redundant_pps_bsf = { .name = "h264_redundant_pps", .priv_data_size = sizeof(H264RedundantPPSContext), .init = &h264_redundant_pps_init, - .flush = &h264_redundant_pps_flush, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, .codec_ids = h264_redundant_pps_codec_ids, From 5892a55d55dcb17702eff35717ca7cafcd4dc658 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 18:43:34 +0100 Subject: [PATCH 346/894] avcodec/h264_redundant_pps_bsf: Support multiple input PPS Up until now, the h264_redundant_pps_bsf stored the initial value of pic_init_qp_minus26 of the most recently encountered PPS; it also modified the slices based upon to assumption that the most recent PPS is the PPS the slice belongs to. Yet this assumption is flawed, as there can be several PPS with different IDs that are visible at any given time. If these have different pic_init_qp_minus26 values, the output can be invalid. Fix this by directly using the pic_init_qp_minus26 value of the input PPS. Signed-off-by: Andreas Rheinhardt --- libavcodec/h264_redundant_pps_bsf.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index 4b2831fb04..5efcf5ea5d 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -32,7 +32,6 @@ typedef struct H264RedundantPPSContext { CBSBSFContext common; int global_pic_init_qp; - int current_pic_init_qp; } H264RedundantPPSContext; @@ -50,9 +49,7 @@ static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, return err; pps = unit->content; - // Record the current value of pic_init_qp in order to fix up - // following slices, then overwrite with the global value. - ctx->current_pic_init_qp = pps->pic_init_qp_minus26 + 26; + // Overwrite pic_init_qp with the global value. pps->pic_init_qp_minus26 = ctx->global_pic_init_qp - 26; // Some PPSs have this set, so it must be set in all of them. @@ -66,10 +63,13 @@ static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, H264RawSliceHeader *slice) { - int qp; + const CodedBitstreamH264Context *const in = ctx->common.input->priv_data; + const H264RawPPS *const pps = in->pps[slice->pic_parameter_set_id]; - qp = ctx->current_pic_init_qp + slice->slice_qp_delta; - slice->slice_qp_delta = qp - ctx->global_pic_init_qp; + // We modified the PPS's qp value, now offset this by applying + // the negative offset to the slices. + slice->slice_qp_delta += pps->pic_init_qp_minus26 + - (ctx->global_pic_init_qp - 26); return 0; } From b574fb472ed168f5a75cd981c98dd34cfe57ff3a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 30 Nov 2021 19:19:06 +0100 Subject: [PATCH 347/894] avcodec/h264_redundant_pps_bsf: Inline constant Signed-off-by: Andreas Rheinhardt --- libavcodec/h264_redundant_pps_bsf.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index 5efcf5ea5d..769946abfd 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -27,11 +27,10 @@ #include "cbs_h264.h" #include "h264.h" +#define NEW_GLOBAL_PIC_INIT_QP 26 typedef struct H264RedundantPPSContext { CBSBSFContext common; - - int global_pic_init_qp; } H264RedundantPPSContext; @@ -50,7 +49,7 @@ static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, pps = unit->content; // Overwrite pic_init_qp with the global value. - pps->pic_init_qp_minus26 = ctx->global_pic_init_qp - 26; + pps->pic_init_qp_minus26 = NEW_GLOBAL_PIC_INIT_QP - 26; // Some PPSs have this set, so it must be set in all of them. // (Slices which do not use such a PPS on input will still have @@ -69,7 +68,7 @@ static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, // We modified the PPS's qp value, now offset this by applying // the negative offset to the slices. slice->slice_qp_delta += pps->pic_init_qp_minus26 - - (ctx->global_pic_init_qp - 26); + - (NEW_GLOBAL_PIC_INIT_QP - 26); return 0; } @@ -119,10 +118,6 @@ static const CBSBSFType h264_redundant_pps_type = { static int h264_redundant_pps_init(AVBSFContext *bsf) { - H264RedundantPPSContext *ctx = bsf->priv_data; - - ctx->global_pic_init_qp = 26; - return ff_cbs_bsf_generic_init(bsf, &h264_redundant_pps_type); } From a4798a5d5109cd9c1b5682efe19660e825da97e6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 27 Nov 2021 10:50:47 +0100 Subject: [PATCH 348/894] all: Use av_memdup() where appropriate Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavcodec/decode.c | 4 +--- libavcodec/dvbsubdec.c | 8 ++------ libavcodec/g723_1enc.c | 3 +-- libavformat/hdsenc.c | 6 ++---- libavformat/mpegts.c | 3 +-- libavformat/oggparsevorbis.c | 3 +-- libavformat/rtsp.c | 3 +-- libavutil/bprint.c | 6 ++---- 8 files changed, 11 insertions(+), 25 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index c44724d150..52bf5dcd33 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1104,12 +1104,10 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) avctx->sw_pix_fmt = fmt[n - 1]; } - choices = av_malloc_array(n + 1, sizeof(*choices)); + choices = av_memdup(fmt, (n + 1) * sizeof(*choices)); if (!choices) return AV_PIX_FMT_NONE; - memcpy(choices, fmt, (n + 1) * sizeof(*choices)); - for (;;) { // Remove the previous hwaccel, if there was one. hwaccel_uninit(avctx); diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index d192f3251d..81ccaf4c57 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -823,14 +823,12 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou } memcpy(rect->data[1], clut_table, (1 << region->depth) * sizeof(*clut_table)); - rect->data[0] = av_malloc(region->buf_size); + rect->data[0] = av_memdup(region->pbuf, region->buf_size); if (!rect->data[0]) { ret = AVERROR(ENOMEM); goto fail; } - memcpy(rect->data[0], region->pbuf, region->buf_size); - if ((clut == &default_clut && ctx->compute_clut < 0) || ctx->compute_clut == 1) { if (!region->has_computed_clut) { compute_default_clut(ctx, region->computed_clut, rect, rect->w, rect->h); @@ -1074,12 +1072,10 @@ static int dvbsub_parse_clut_segment(AVCodecContext *avctx, clut = get_clut(ctx, clut_id); if (!clut) { - clut = av_malloc(sizeof(*clut)); + clut = av_memdup(&default_clut, sizeof(*clut)); if (!clut) return AVERROR(ENOMEM); - memcpy(clut, &default_clut, sizeof(*clut)); - clut->id = clut_id; clut->version = -1; diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c index 2b3cccee09..2a8149b4cd 100644 --- a/libavcodec/g723_1enc.c +++ b/libavcodec/g723_1enc.c @@ -1116,10 +1116,9 @@ static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, HFParam hf[4]; /* duplicate input */ - start = in = av_malloc(frame->nb_samples * sizeof(int16_t)); + start = in = av_memdup(frame->data[0], frame->nb_samples * sizeof(int16_t)); if (!in) return AVERROR(ENOMEM); - memcpy(in, frame->data[0], frame->nb_samples * sizeof(int16_t)); highpass_filter(in, &p->hpf_fir_mem, &p->hpf_iir_mem); diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index e5353bac65..64d9f1413d 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -93,19 +93,17 @@ static int parse_header(OutputStream *os, const uint8_t *buf, int buf_size) if (os->nb_extra_packets >= FF_ARRAY_ELEMS(os->extra_packets)) return AVERROR_INVALIDDATA; os->extra_packet_sizes[os->nb_extra_packets] = size; - os->extra_packets[os->nb_extra_packets] = av_malloc(size); + os->extra_packets[os->nb_extra_packets] = av_memdup(buf, size); if (!os->extra_packets[os->nb_extra_packets]) return AVERROR(ENOMEM); - memcpy(os->extra_packets[os->nb_extra_packets], buf, size); os->nb_extra_packets++; } else if (type == 0x12) { if (os->metadata) return AVERROR_INVALIDDATA; os->metadata_size = size - 11 - 4; - os->metadata = av_malloc(os->metadata_size); + os->metadata = av_memdup(buf + 11, os->metadata_size); if (!os->metadata) return AVERROR(ENOMEM); - memcpy(os->metadata, buf + 11, os->metadata_size); } buf += size; buf_size -= size; diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 36ab7ab3af..2479cb6f7d 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -938,10 +938,9 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, // audio track - add a second stream for this AVStream *sub_st; // priv_data cannot be shared between streams - PESContext *sub_pes = av_malloc(sizeof(*sub_pes)); + PESContext *sub_pes = av_memdup(pes, sizeof(*sub_pes)); if (!sub_pes) return AVERROR(ENOMEM); - memcpy(sub_pes, pes, sizeof(*sub_pes)); sub_st = avformat_new_stream(pes->stream, NULL); if (!sub_st) { diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 77e8d301b2..e1ef510892 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -320,10 +320,9 @@ static int vorbis_header(AVFormatContext *s, int idx) return priv->vp ? 0 : AVERROR_INVALIDDATA; priv->len[pkt_type >> 1] = os->psize; - priv->packet[pkt_type >> 1] = av_mallocz(os->psize); + priv->packet[pkt_type >> 1] = av_memdup(os->buf + os->pstart, os->psize); if (!priv->packet[pkt_type >> 1]) return AVERROR(ENOMEM); - memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize); if (os->buf[os->pstart] == 1) { const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */ unsigned blocksize, bs0, bs1; diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index e6a4993acd..cd3d284da6 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -387,10 +387,9 @@ static void copy_default_source_addrs(struct RTSPSource **addrs, int count, int i; for (i = 0; i < count; i++) { rtsp_src = addrs[i]; - rtsp_src2 = av_malloc(sizeof(*rtsp_src2)); + rtsp_src2 = av_memdup(rtsp_src, sizeof(*rtsp_src)); if (!rtsp_src2) continue; - memcpy(rtsp_src2, rtsp_src, sizeof(*rtsp_src)); dynarray_add(dest, dest_count, rtsp_src2); } } diff --git a/libavutil/bprint.c b/libavutil/bprint.c index a6849d7178..ea51d9b09c 100644 --- a/libavutil/bprint.c +++ b/libavutil/bprint.c @@ -244,10 +244,8 @@ int av_bprint_finalize(AVBPrint *buf, char **ret_str) str = buf->str; buf->str = NULL; } else { - str = av_malloc(real_size); - if (str) - memcpy(str, buf->str, real_size); - else + str = av_memdup(buf->str, real_size); + if (!str) ret = AVERROR(ENOMEM); } *ret_str = str; From 01d158d1c8295474fa2034612487b36a47adfd1d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 1 Dec 2021 15:22:05 +0100 Subject: [PATCH 349/894] all: Remove unused-but-set variables Newer versions of Clang detect this and emit warnings for it. Signed-off-by: Andreas Rheinhardt --- libavcodec/aaccoder.c | 3 +-- libavcodec/cinepakenc.c | 3 --- libavcodec/error_resilience.c | 3 --- libavcodec/imc.c | 5 ++--- libavcodec/j2kenc.c | 2 -- libavcodec/roqvideoenc.c | 2 -- libavfilter/af_astats.c | 4 ---- libswresample/tests/swresample.c | 8 -------- 8 files changed, 3 insertions(+), 27 deletions(-) diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index 11b0559e1c..7bbd4d5b2e 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -414,11 +414,10 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s, start = 0; for (g = 0; g < sce->ics.num_swb; g++) { int nz = 0; - float uplim = 0.0f, energy = 0.0f; + float uplim = 0.0f; for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; uplim += band->threshold; - energy += band->energy; if (band->energy <= band->threshold || band->threshold == 0.0f) { sce->zeroes[(w+w2)*16+g] = 1; continue; diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index edb553f0db..0574b125d7 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -705,7 +705,6 @@ static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; int *codebook = v1mode ? info->v1_codebook : info->v4_codebook; int size = v1mode ? info->v1_size : info->v4_size; - int64_t total_error = 0; uint8_t vq_pict_buf[(MB_AREA * 3) / 2]; uint8_t *sub_data[4], *vq_data[4]; int sub_linesize[4], vq_linesize[4]; @@ -795,7 +794,6 @@ static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], mb->v1_error = compute_mb_distortion(s, sub_data, sub_linesize, vq_data, vq_linesize); - total_error += mb->v1_error; } else { for (k = 0; k < 4; k++) mb->v4_vector[k] = s->codebook_closest[i + k]; @@ -805,7 +803,6 @@ static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], mb->v4_error = compute_mb_distortion(s, sub_data, sub_linesize, vq_data, vq_linesize); - total_error += mb->v4_error; } i += v1mode ? 1 : 4; } diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index f13be7b918..91cd8a4444 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -476,8 +476,6 @@ static void guess_mv(ERContext *s) none_left = 1; changed = 1; for (pass = 0; (changed || pass < 2) && pass < 10; pass++) { - int score_sum = 0; - changed = 0; for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) { const int mb_x = blocklist[blocklist_index][0]; @@ -668,7 +666,6 @@ skip_mean_and_median: best_pred = j; } } - score_sum += best_score; s->mv[0][0][0] = mv_predictor[best_pred][0]; s->mv[0][0][1] = mv_predictor[best_pred][1]; diff --git a/libavcodec/imc.c b/libavcodec/imc.c index cbe3edeeec..116c273ba0 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -829,7 +829,7 @@ static void imc_get_coeffs(AVCodecContext *avctx, static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx) { int i, j; - int bits, summer; + int summer; for (i = 0; i < BANDS; i++) { chctx->sumLenArr[i] = 0; @@ -853,7 +853,7 @@ static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx) } /* calculate bits left, bits needed and adjust bit allocation */ - bits = summer = 0; + summer = 0; for (i = 0; i < BANDS; i++) { if (chctx->bandFlagsBuf[i]) { @@ -863,7 +863,6 @@ static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx) chctx->CWlengthT[j] = 0; } } - bits += chctx->skipFlagBits[i]; summer -= chctx->skipFlagBits[i]; } } diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index fa6fc208f5..c06752f43a 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1272,7 +1272,6 @@ static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) double min = DBL_MAX; double max = 0; double thresh; - int tile_disto = 0; Jpeg2000CodingStyle *codsty = &s->codsty; @@ -1294,7 +1293,6 @@ static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) int dr; double dd, drslope; - tile_disto += pass->disto; if (passno == 0) { dr = (int32_t)pass->rate; dd = pass->disto; diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 684dbe0af5..95012f7c1a 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -666,7 +666,6 @@ static void reconstruct_and_encode_image(RoqEncContext *enc, int i, j, k; int x, y; int subX, subY; - int dist=0; roq_qcell *qcell; CelEvaluation *eval; @@ -692,7 +691,6 @@ static void reconstruct_and_encode_image(RoqEncContext *enc, x = eval->sourceX; y = eval->sourceY; - dist += eval->eval_dist[eval->best_coding]; switch (eval->best_coding) { case RoQ_ID_MOT: diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index 0621d18b35..3955a4e8e9 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -403,7 +403,6 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) max_sigma_x = 0, diff1_sum = 0, diff1_sum_x2 = 0, - sigma_x = 0, sigma_x2 = 0, noise_floor = 0, entropy = 0, @@ -428,7 +427,6 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) diff1_sum_x2 += p->diff1_sum_x2; min_sigma_x2 = FFMIN(min_sigma_x2, p->min_sigma_x2); max_sigma_x2 = FFMAX(max_sigma_x2, p->max_sigma_x2); - sigma_x += p->sigma_x; sigma_x2 += p->sigma_x2; noise_floor = FFMAX(noise_floor, p->noise_floor); noise_floor_count += p->noise_floor_count; @@ -659,7 +657,6 @@ static void print_stats(AVFilterContext *ctx) max_sigma_x = 0, diff1_sum_x2 = 0, diff1_sum = 0, - sigma_x = 0, sigma_x2 = 0, noise_floor = 0, entropy = 0, @@ -684,7 +681,6 @@ static void print_stats(AVFilterContext *ctx) diff1_sum += p->diff1_sum; min_sigma_x2 = FFMIN(min_sigma_x2, p->min_sigma_x2); max_sigma_x2 = FFMAX(max_sigma_x2, p->max_sigma_x2); - sigma_x += p->sigma_x; sigma_x2 += p->sigma_x2; noise_floor = FFMAX(noise_floor, p->noise_floor); p->entropy = calc_entropy(s, p); diff --git a/libswresample/tests/swresample.c b/libswresample/tests/swresample.c index 53896585e2..14a8f14f3e 100644 --- a/libswresample/tests/swresample.c +++ b/libswresample/tests/swresample.c @@ -362,16 +362,12 @@ int main(int argc, char **argv){ for(ch=0; ch Date: Wed, 1 Dec 2021 16:02:23 +0100 Subject: [PATCH 350/894] swscale/yuv2rgb: Silence a set-but-unused-variable warning Signed-off-by: Andreas Rheinhardt --- libswscale/yuv2rgb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c index 353de2f822..76232cb364 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -145,8 +145,8 @@ const int *sws_getCoefficients(int colorspace) dst_type av_unused *r, *g, *b; \ const uint8_t *py_1 = src[0] + y * srcStride[0]; \ const uint8_t *py_2 = py_1 + srcStride[0]; \ - const uint8_t *pu = src[1] + (y >> 1) * srcStride[1]; \ - const uint8_t *pv = src[2] + (y >> 1) * srcStride[2]; \ + const uint8_t av_unused *pu = src[1] + (y >> 1) * srcStride[1]; \ + const uint8_t av_unused *pv = src[2] + (y >> 1) * srcStride[2]; \ const uint8_t av_unused *pa_1, *pa_2; \ unsigned int h_size = c->dstW >> 3; \ if (alpha) { \ From cf8925a0965a75f22cddb1cc42e11871ccf84c15 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 1 Dec 2021 16:36:19 +0100 Subject: [PATCH 351/894] fftools/ffmpeg_filter: Avoid DynBuf-API for writing strings It is not really natural, it requires internal allocations of its own and its error handling is horrible (i.e. the implicit (re)allocations here are unchecked). Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_filter.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 452b689d62..47bbb67ce0 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -201,17 +201,15 @@ static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) AVFilterContext *ctx = inout->filter_ctx; AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; - AVIOContext *pb; - uint8_t *res = NULL; + char *res; - if (avio_open_dyn_buf(&pb) < 0) - exit_program(1); - - avio_printf(pb, "%s", ctx->filter->name); if (nb_pads > 1) - avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx)); - avio_w8(pb, 0); - avio_close_dyn_buf(pb, &res); + res = av_strdup(ctx->filter->name); + else + res = av_asprintf("%s:%s", ctx->filter->name, + avfilter_pad_get_name(pads, inout->pad_idx)); + if (!res) + exit_program(1); return res; } From efc323062c20aaead8fb5805b7f69b4f071cb319 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 1 Dec 2021 17:13:32 +0100 Subject: [PATCH 352/894] fftools/ffmpeg_filter: Avoid DynBuf API to improve error checks choose_pix_fmts() used the dynamic buffer API to write strings; as is common among uses of this API, only opening the dynamic buffer was checked, but not the end result, leading to crashes in case of allocation failure. Furthermore, some static strings were duplicated; the allocations performed here were not properly checked: Allocation failure would be treated as "could not determine pixel format". The first issue is fixed by switching to the AVBPrint API which allows to easily perform checks at the end. Furthermore, the internal buffer avoids almost all allocations in case the AVBPrint is used. The AVBPrint also allows to solve the second issue in an elegant way, because it allows to return the static strings directly. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_filter.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 47bbb67ce0..dab0f28819 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -83,7 +83,10 @@ static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx return target; } -static char *choose_pix_fmts(OutputFilter *ofilter) +/* May return NULL (no pixel format found), a static string or a string + * backed by the bprint. Nothing has been written to the AVBPrint in case + * NULL is returned. The AVBPrint provided should be clean. */ +static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) { OutputStream *ost = ofilter->ost; const AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); @@ -96,18 +99,12 @@ static char *choose_pix_fmts(OutputFilter *ofilter) AVFILTER_AUTO_CONVERT_NONE); if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) return NULL; - return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt)); + return av_get_pix_fmt_name(ost->enc_ctx->pix_fmt); } if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt))); + return av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)); } else if (ost->enc && ost->enc->pix_fmts) { const enum AVPixelFormat *p; - AVIOContext *s = NULL; - uint8_t *ret; - int len; - - if (avio_open_dyn_buf(&s) < 0) - exit_program(1); p = ost->enc->pix_fmts; if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { @@ -116,11 +113,11 @@ static char *choose_pix_fmts(OutputFilter *ofilter) for (; *p != AV_PIX_FMT_NONE; p++) { const char *name = av_get_pix_fmt_name(*p); - avio_printf(s, "%s|", name); + av_bprintf(bprint, "%s%c", name, p[1] == AV_PIX_FMT_NONE ? '\0' : '|'); } - len = avio_close_dyn_buf(s, &ret); - ret[len - 1] = 0; - return ret; + if (!av_bprint_is_complete(bprint)) + exit_program(1); + return bprint->str; } else return NULL; } @@ -416,12 +413,13 @@ static int insert_filter(AVFilterContext **last_filter, int *pad_idx, static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { - char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; AVFilterContext *last_filter = out->filter_ctx; + AVBPrint bprint; int pad_idx = out->pad_idx; int ret; + const char *pix_fmts; char name[255]; snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); @@ -457,13 +455,14 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if ((pix_fmts = choose_pix_fmts(ofilter))) { + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + if ((pix_fmts = choose_pix_fmts(ofilter, &bprint))) { AVFilterContext *filter; ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("format"), "format", pix_fmts, NULL, fg->graph); - av_freep(&pix_fmts); + av_bprint_finalize(&bprint, NULL); if (ret < 0) return ret; if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) From 84f037edc2065db348879a9312720a93e54a4942 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 16:51:17 +0100 Subject: [PATCH 353/894] avdevice/lavfi: Don't unnecessarily write '\0' to AVBPrint An AVBPrint's internal string is always already zero-terminated; writing another '\0' is unnecessary as long as one treats the string only as a C-string. Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index d9083ad984..2659c8508a 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -156,9 +156,6 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) av_bprint_init(&graph_file_pb, 0, AV_BPRINT_SIZE_UNLIMITED); ret = avio_read_to_bprint(avio, &graph_file_pb, INT_MAX); avio_closep(&avio); - av_bprint_chars(&graph_file_pb, '\0', 1); - if (!ret && !av_bprint_is_complete(&graph_file_pb)) - ret = AVERROR(ENOMEM); if (ret) { av_bprint_finalize(&graph_file_pb, NULL); goto end; From 83ae589359203e83a7e9c1e96eb3f02f5a5bfa6b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 18:08:13 +0100 Subject: [PATCH 354/894] avdevice/lavfi: Use dedicated pointer to access st->codecpar Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 2659c8508a..209ebed5fd 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -317,26 +317,27 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) AVFilterContext *sink = lavfi->sinks[lavfi->stream_sink_map[i]]; AVRational time_base = av_buffersink_get_time_base(sink); AVStream *st = avctx->streams[i]; - st->codecpar->codec_type = av_buffersink_get_type(sink); + AVCodecParameters *const par = st->codecpar; avpriv_set_pts_info(st, 64, time_base.num, time_base.den); + par->codec_type = av_buffersink_get_type(sink); if (av_buffersink_get_type(sink) == AVMEDIA_TYPE_VIDEO) { - st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codecpar->format = av_buffersink_get_format(sink); - st->codecpar->width = av_buffersink_get_w(sink); - st->codecpar->height = av_buffersink_get_h(sink); + par->codec_id = AV_CODEC_ID_RAWVIDEO; + par->format = av_buffersink_get_format(sink); + par->width = av_buffersink_get_w(sink); + par->height = av_buffersink_get_h(sink); st ->sample_aspect_ratio = - st->codecpar->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); + par->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); avctx->probesize = FFMAX(avctx->probesize, av_buffersink_get_w(sink) * av_buffersink_get_h(sink) * av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(av_buffersink_get_format(sink))) * 30); } else if (av_buffersink_get_type(sink) == AVMEDIA_TYPE_AUDIO) { - st->codecpar->codec_id = av_get_pcm_codec(av_buffersink_get_format(sink), -1); - st->codecpar->channels = av_buffersink_get_channels(sink); - st->codecpar->format = av_buffersink_get_format(sink); - st->codecpar->sample_rate = av_buffersink_get_sample_rate(sink); - st->codecpar->channel_layout = av_buffersink_get_channel_layout(sink); - if (st->codecpar->codec_id == AV_CODEC_ID_NONE) + par->channels = av_buffersink_get_channels(sink); + par->sample_rate = av_buffersink_get_sample_rate(sink); + par->channel_layout = av_buffersink_get_channel_layout(sink); + par->format = av_buffersink_get_format(sink); + par->codec_id = av_get_pcm_codec(av_buffersink_get_format(sink), -1); + if (par->codec_id == AV_CODEC_ID_NONE) av_log(avctx, AV_LOG_ERROR, "Could not find PCM codec for sample format %s.\n", av_get_sample_fmt_name(av_buffersink_get_format(sink))); From 88af0962ef76582a1f4772ee81816512a6646edb Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 18:35:50 +0100 Subject: [PATCH 355/894] avdevice/lavfi: Avoid calling av_buffersink_get_* multiple times Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 209ebed5fd..878bb193af 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -320,27 +320,27 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) AVCodecParameters *const par = st->codecpar; avpriv_set_pts_info(st, 64, time_base.num, time_base.den); par->codec_type = av_buffersink_get_type(sink); - if (av_buffersink_get_type(sink) == AVMEDIA_TYPE_VIDEO) { + if (par->codec_type == AVMEDIA_TYPE_VIDEO) { + int64_t probesize; par->codec_id = AV_CODEC_ID_RAWVIDEO; par->format = av_buffersink_get_format(sink); par->width = av_buffersink_get_w(sink); par->height = av_buffersink_get_h(sink); + probesize = par->width * par->height * 30 * + av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(par->format)); + avctx->probesize = FFMAX(avctx->probesize, probesize); st ->sample_aspect_ratio = par->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); - avctx->probesize = FFMAX(avctx->probesize, - av_buffersink_get_w(sink) * av_buffersink_get_h(sink) * - av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(av_buffersink_get_format(sink))) * - 30); - } else if (av_buffersink_get_type(sink) == AVMEDIA_TYPE_AUDIO) { + } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { par->channels = av_buffersink_get_channels(sink); par->sample_rate = av_buffersink_get_sample_rate(sink); par->channel_layout = av_buffersink_get_channel_layout(sink); par->format = av_buffersink_get_format(sink); - par->codec_id = av_get_pcm_codec(av_buffersink_get_format(sink), -1); + par->codec_id = av_get_pcm_codec(par->format, -1); if (par->codec_id == AV_CODEC_ID_NONE) av_log(avctx, AV_LOG_ERROR, "Could not find PCM codec for sample format %s.\n", - av_get_sample_fmt_name(av_buffersink_get_format(sink))); + av_get_sample_fmt_name(par->format)); } } From 60a2c74a5eaf8d4ab16a68842be3b9cfbd45b467 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 18:40:39 +0100 Subject: [PATCH 356/894] avdevice/lavfi: Make array static const Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 878bb193af..b208b1a928 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -269,11 +269,10 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) if (ret < 0) goto end; } else if (type == AVMEDIA_TYPE_AUDIO) { - enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_U8, - AV_SAMPLE_FMT_S16, - AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_FLT, - AV_SAMPLE_FMT_DBL, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL, -1 + }; ret = avfilter_graph_create_filter(&sink, abuffersink, inout->name, NULL, From b7e3ae19b8d3dc1b14c600220a47171e5e3ef746 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 19:19:19 +0100 Subject: [PATCH 357/894] avdevice/lavfi: Simplify setting sample_fmts The length of this list is a compile-time constant, so there is no need to calculate it again at runtime. (This also avoids an implicit requirement of -1 == AV_SAMPLE_FMT_NONE.) Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index b208b1a928..d63a6f66b3 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -271,14 +271,15 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) } else if (type == AVMEDIA_TYPE_AUDIO) { static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL, -1 + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL, }; ret = avfilter_graph_create_filter(&sink, abuffersink, inout->name, NULL, NULL, lavfi->graph); if (ret >= 0) - ret = av_opt_set_int_list(sink, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN); + ret = av_opt_set_bin(sink, "sample_fmts", (const uint8_t*)sample_fmts, + sizeof(sample_fmts), AV_OPT_SEARCH_CHILDREN); if (ret < 0) goto end; ret = av_opt_set_int(sink, "all_channel_counts", 1, From 61bbd0cf3c2ae1f8502243a5695d68cbd3b20758 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 20:57:23 +0100 Subject: [PATCH 358/894] avdevice/lavfi: Don't require AV_PIX_FMT_NONE == -1 Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavdevice/lavfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index d63a6f66b3..710ad7c530 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -76,7 +76,7 @@ static int *create_all_formats(int n) if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) fmts[j++] = i; } - fmts[j] = -1; + fmts[j] = AV_PIX_FMT_NONE; return fmts; } From 03ab1de429a43a99c6de0c0d6ec1d275349dc133 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 2 Dec 2021 21:08:38 +0100 Subject: [PATCH 359/894] avfilter/buffersink: Remove outdated comments These lists have size fields since e48ded8551172b58a78f30303a81dfce125344e0. Reviewed-by: Nicolas George Signed-off-by: Andreas Rheinhardt --- libavfilter/buffersink.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index b8ddafec35..c0215669e7 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -43,18 +43,18 @@ typedef struct BufferSinkContext { unsigned warning_limit; /* only used for video */ - enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1 + enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats int pixel_fmts_size; /* only used for audio */ - enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE + enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats int sample_fmts_size; - int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1 + int64_t *channel_layouts; ///< list of accepted channel layouts int channel_layouts_size; - int *channel_counts; ///< list of accepted channel counts, terminated by -1 + int *channel_counts; ///< list of accepted channel counts int channel_counts_size; int all_channel_counts; - int *sample_rates; ///< list of accepted sample rates, terminated by -1 + int *sample_rates; ///< list of accepted sample rates int sample_rates_size; AVFrame *peeked_frame; From b236ef0a594e20038b4045e2fecd414f1886d212 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 25 Nov 2021 18:26:20 +0100 Subject: [PATCH 360/894] lavu/avframe: add a time_base field This adds a time_base field to AVFrame, as an analogue to the AVPacket.time_base field. --- doc/APIchanges | 3 +++ libavutil/frame.c | 2 ++ libavutil/frame.h | 8 ++++++++ libavutil/version.h | 2 +- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index bc9f4e38da..4788dd576d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-03 - xxxxxxxxxx - lavu 57.10.100 - frame.h + Add AVFrame.time_base + 2021-11-22 - xxxxxxxxxx - lavu 57.9.100 - pixfmt.h Add AV_PIX_FMT_P210, AV_PIX_FMT_P410, AV_PIX_FMT_P216, and AV_PIX_FMT_P416. diff --git a/libavutil/frame.c b/libavutil/frame.c index d4d3ad6988..64eed5b0dd 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -63,6 +63,7 @@ static void get_frame_defaults(AVFrame *frame) frame->pkt_duration = 0; frame->pkt_pos = -1; frame->pkt_size = -1; + frame->time_base = (AVRational){ 0, 1 }; frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational){ 0, 1 }; frame->format = -1; /* unknown */ @@ -278,6 +279,7 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) dst->pkt_pos = src->pkt_pos; dst->pkt_size = src->pkt_size; dst->pkt_duration = src->pkt_duration; + dst->time_base = src->time_base; dst->reordered_opaque = src->reordered_opaque; dst->quality = src->quality; dst->best_effort_timestamp = src->best_effort_timestamp; diff --git a/libavutil/frame.h b/libavutil/frame.h index 753234792e..882b5afbde 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -421,6 +421,14 @@ typedef struct AVFrame { */ int64_t pkt_dts; + /** + * Time base for the timestamps in this frame. + * In the future, this field may be set on frames output by decoders or + * filters, but its value will be by default ignored on input to encoders + * or filters. + */ + AVRational time_base; + /** * picture number in bitstream order */ diff --git a/libavutil/version.h b/libavutil/version.h index a2615cd299..017fc277a6 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 9 +#define LIBAVUTIL_VERSION_MINOR 10 #define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 3c74ffb01ac3aa567d166362237117a6ca7c0775 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 3 Dec 2021 12:07:34 +0800 Subject: [PATCH 361/894] avformat/aviobuf: check if read_packet() exist before read_packet_wrapper() without it, read_packet_wrapper() will return AVERROR(EINVAL) and avio_read will be failed. Signed-off-by: Limin Wang --- libavformat/aviobuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 5da4dea7b6..14688a2262 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -646,7 +646,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) while (size > 0) { len = FFMIN(s->buf_end - s->buf_ptr, size); if (len == 0 || s->write_flag) { - if((s->direct || size > s->buffer_size) && !s->update_checksum) { + if((s->direct || size > s->buffer_size) && !s->update_checksum && s->read_packet) { // bypass the buffer and read data directly into buf len = read_packet_wrapper(s, buf, size); if (len == AVERROR_EOF) { From 98054e4f018fefb83c1903de99cdd9e9c3394e85 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 2 Dec 2021 18:12:12 +0800 Subject: [PATCH 362/894] avformat/rtsp: load the sdp file with avio_read_to_bprint() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this allows getting rid of the hardcoded max size of SDP. Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/rtsp.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index cd3d284da6..deaed34db4 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -2372,9 +2372,9 @@ static int sdp_read_header(AVFormatContext *s) { RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; - int size, i, err; - char *content; + int i, err; char url[MAX_URL_SIZE]; + AVBPrint bp; if (!ff_network_init()) return AVERROR(EIO); @@ -2385,22 +2385,15 @@ static int sdp_read_header(AVFormatContext *s) rt->lower_transport = RTSP_LOWER_TRANSPORT_CUSTOM; /* read the whole sdp file */ - /* XXX: better loading */ - content = av_malloc(SDP_MAX_SIZE); - if (!content) { + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); + err = avio_read_to_bprint(s->pb, &bp, INT_MAX); + if (err < 0 ) { ff_network_close(); - return AVERROR(ENOMEM); + av_bprint_finalize(&bp, NULL); + return err; } - size = avio_read(s->pb, content, SDP_MAX_SIZE - 1); - if (size <= 0) { - av_free(content); - ff_network_close(); - return AVERROR_INVALIDDATA; - } - content[size] ='\0'; - - err = ff_sdp_parse(s, content); - av_freep(&content); + err = ff_sdp_parse(s, bp.str); + av_bprint_finalize(&bp, NULL); if (err) goto fail; /* open each RTP stream */ From d782c746a0d31b48b4484421ab80a472db954bc7 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 2 Dec 2021 18:33:58 +0800 Subject: [PATCH 363/894] avformat/rtspdec: get rid of the hardcoded max size for sdp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/rtspdec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 0e91e3e315..2ada29a2d3 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -172,7 +172,7 @@ static int rtsp_read_announce(AVFormatContext *s) { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; - char sdp[SDP_MAX_SIZE]; + char *sdp; int ret; ret = rtsp_read_request(s, &request, "ANNOUNCE"); @@ -185,18 +185,24 @@ static int rtsp_read_announce(AVFormatContext *s) rtsp_send_reply(s, RTSP_STATUS_SERVICE, NULL, request.seq); return AVERROR_OPTION_NOT_FOUND; } - if (request.content_length && request.content_length < sizeof(sdp) - 1) { + if (request.content_length) { + sdp = av_malloc(request.content_length + 1); + if (!sdp) + return AVERROR(ENOMEM); + /* Read SDP */ if (ffurl_read_complete(rt->rtsp_hd, sdp, request.content_length) < request.content_length) { av_log(s, AV_LOG_ERROR, "Unable to get complete SDP Description in ANNOUNCE\n"); rtsp_send_reply(s, RTSP_STATUS_INTERNAL, NULL, request.seq); + av_free(sdp); return AVERROR(EIO); } sdp[request.content_length] = '\0'; av_log(s, AV_LOG_VERBOSE, "SDP: %s\n", sdp); ret = ff_sdp_parse(s, sdp); + av_free(sdp); if (ret) return ret; rtsp_send_reply(s, RTSP_STATUS_OK, NULL, request.seq); From a7df966c82b991ea4f05c40ff5efab65ce56308e Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 2 Dec 2021 21:15:22 +0800 Subject: [PATCH 364/894] avcodec/videotoolbox: fix use of unknown builtin '__builtin_available' Old system is: OSX version: 10.11.6 Apple LLVM version 8.0.0 (clang-800.0.42.1) Target: x86_64-apple-darwin15.6.0 Signed-off-by: Limin Wang --- libavcodec/videotoolbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 284da97541..519f55a9ab 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -895,7 +895,7 @@ static int videotoolbox_start(AVCodecContext *avctx) break; } -#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) +#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) && AV_HAS_BUILTIN(__builtin_available) if (avctx->codec_id == AV_CODEC_ID_PRORES) { if (__builtin_available(macOS 10.9, *)) { VTRegisterProfessionalVideoWorkflowVideoDecoders(); @@ -903,7 +903,7 @@ static int videotoolbox_start(AVCodecContext *avctx) } #endif -#if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) +#if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) && AV_HAS_BUILTIN(__builtin_available) if (__builtin_available(macOS 11.0, *)) { VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type); } From c6f4e10111debf5b547a399661a5fe997d761033 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Mon, 22 Nov 2021 00:25:16 +0100 Subject: [PATCH 365/894] avformat: do not use AVIO_FLAG_* with avio_alloc_context The documentation states that here 0 should be used for read-only and 1 for a writable buffer. AVIO_FLAG_WRITE however is 2, while it works due to the way the flag is handled internally, it is still wrong according to the documentation. Additionally it makes it seem as if the AVIO_FLAG_* values could be used here, which is actually not true, as when AVIO_FLAG_READ would be used here it would create a writable buffer as AVIO_FLAG_READ is defined as 1. Signed-off-by: Anton Khirnov --- libavformat/hdsenc.c | 2 +- libavformat/segment.c | 2 +- libavformat/smoothstreamingenc.c | 2 +- libavformat/tests/movenc.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index 64d9f1413d..2a52019120 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -368,7 +368,7 @@ static int hds_write_header(AVFormatContext *s) ctx->flags = s->flags; ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), - AVIO_FLAG_WRITE, os, + 1, os, NULL, hds_write, NULL); if (!ctx->pb) { return AVERROR(ENOMEM); diff --git a/libavformat/segment.c b/libavformat/segment.c index 9861462405..d531286c31 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -569,7 +569,7 @@ static int open_null_ctx(AVIOContext **ctx) uint8_t *buf = av_malloc(buf_size); if (!buf) return AVERROR(ENOMEM); - *ctx = avio_alloc_context(buf, buf_size, AVIO_FLAG_WRITE, NULL, NULL, NULL, NULL); + *ctx = avio_alloc_context(buf, buf_size, 1, NULL, NULL, NULL, NULL); if (!*ctx) { av_free(buf); return AVERROR(ENOMEM); diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 27b59c299c..6bede7c254 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -335,7 +335,7 @@ static int ism_write_header(AVFormatContext *s) st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; st->time_base = s->streams[i]->time_base; - ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, ism_write, ism_seek); + ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), 1, os, NULL, ism_write, ism_seek); if (!ctx->pb) { return AVERROR(ENOMEM); } diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index 04155dde76..2af72f11c7 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -186,7 +186,7 @@ static void init_fps(int bf, int audio_preroll, int fps) ctx->oformat = av_guess_format(format, NULL, NULL); if (!ctx->oformat) exit(1); - ctx->pb = avio_alloc_context(iobuf, iobuf_size, AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL); + ctx->pb = avio_alloc_context(iobuf, iobuf_size, 1, NULL, NULL, io_write, NULL); if (!ctx->pb) exit(1); ctx->pb->write_data_type = io_write_data_type; From 64467cbca2d9d638348eaeaef13511999744cf7a Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Tue, 16 Nov 2021 16:16:22 +0800 Subject: [PATCH 366/894] libavutil/hwcontext_qsv: fix a bug for mapping vaapi frame to qsv The data stored in data[3] in VAAPI AVFrame is VASurfaceID while the data stored in pair->first is the pointer of VASurfaceID, so we need to do cast to make following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen Signed-off-by: Anton Khirnov --- libavutil/hwcontext_qsv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 268be9f8a1..a5d154a24d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1218,7 +1218,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx, case AV_PIX_FMT_VAAPI: { mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; - if (pair->first == src->data[3]) { + if (*(VASurfaceID*)pair->first == (VASurfaceID)src->data[3]) { index = i; break; } From 944c34a94c3150fc84816c3288cc6f2143f1581b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 22 Nov 2021 14:32:02 +0100 Subject: [PATCH 367/894] lavfi/allfilters: move vf_chromaber_vulkan to video section --- libavfilter/allfilters.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2f91562aa2..b1af2cbcc8 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -106,7 +106,6 @@ extern const AVFilter ff_af_bandreject; extern const AVFilter ff_af_bass; extern const AVFilter ff_af_biquad; extern const AVFilter ff_af_bs2b; -extern const AVFilter ff_vf_chromaber_vulkan; extern const AVFilter ff_af_channelmap; extern const AVFilter ff_af_channelsplit; extern const AVFilter ff_af_chorus; @@ -187,6 +186,7 @@ extern const AVFilter ff_vf_boxblur; extern const AVFilter ff_vf_boxblur_opencl; extern const AVFilter ff_vf_bwdif; extern const AVFilter ff_vf_cas; +extern const AVFilter ff_vf_chromaber_vulkan; extern const AVFilter ff_vf_chromahold; extern const AVFilter ff_vf_chromakey; extern const AVFilter ff_vf_chromanr; From b9c928a486fda3c0d79b153591ac86beb1c53708 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 22 Nov 2021 14:39:11 +0100 Subject: [PATCH 368/894] avfilter: add AVFILTER_FLAG_METADATA_ONLY This flag allows distinguishing between filters that actually modify the data and those that only modify metadata or gather some stream information. --- doc/APIchanges | 3 +++ libavfilter/af_acopy.c | 1 + libavfilter/af_aformat.c | 1 + libavfilter/af_anull.c | 1 + libavfilter/af_asdr.c | 1 + libavfilter/af_asetrate.c | 1 + libavfilter/af_ashowinfo.c | 1 + libavfilter/af_asr.c | 1 + libavfilter/af_astats.c | 2 +- libavfilter/af_drmeter.c | 1 + libavfilter/af_replaygain.c | 1 + libavfilter/af_silencedetect.c | 1 + libavfilter/af_volumedetect.c | 1 + libavfilter/avfilter.h | 16 ++++++++++++++++ libavfilter/f_bench.c | 2 ++ libavfilter/f_cue.c | 1 + libavfilter/f_latency.c | 3 ++- libavfilter/f_metadata.c | 6 ++++-- libavfilter/f_perms.c | 6 ++++-- libavfilter/f_realtime.c | 2 ++ libavfilter/f_segment.c | 4 ++-- libavfilter/f_select.c | 2 +- libavfilter/f_sendcmd.c | 2 ++ libavfilter/f_sidedata.c | 6 ++++-- libavfilter/fifo.c | 2 ++ libavfilter/setpts.c | 2 ++ libavfilter/settb.c | 2 ++ libavfilter/split.c | 4 ++-- libavfilter/trim.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_addroi.c | 2 ++ libavfilter/vf_aspect.c | 2 ++ libavfilter/vf_bbox.c | 2 +- libavfilter/vf_blackdetect.c | 2 +- libavfilter/vf_blackframe.c | 1 + libavfilter/vf_copy.c | 1 + libavfilter/vf_cropdetect.c | 2 +- libavfilter/vf_entropy.c | 2 +- libavfilter/vf_find_rect.c | 1 + libavfilter/vf_format.c | 4 ++++ libavfilter/vf_fps.c | 1 + libavfilter/vf_framestep.c | 2 +- libavfilter/vf_freezedetect.c | 1 + libavfilter/vf_identity.c | 8 ++++++-- libavfilter/vf_idet.c | 1 + libavfilter/vf_mestimate.c | 1 + libavfilter/vf_null.c | 1 + libavfilter/vf_ocr.c | 1 + libavfilter/vf_psnr.c | 4 +++- libavfilter/vf_qp.c | 3 ++- libavfilter/vf_readeia608.c | 4 +++- libavfilter/vf_readvitc.c | 1 + libavfilter/vf_scdet.c | 1 + libavfilter/vf_setparams.c | 3 +++ libavfilter/vf_showinfo.c | 1 + libavfilter/vf_ssim.c | 4 +++- libavfilter/vf_vfrdet.c | 1 + libavfilter/vf_vidstabdetect.c | 1 + libavfilter/vf_vif.c | 4 +++- libavfilter/vf_vmafmotion.c | 1 + 60 files changed, 116 insertions(+), 26 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4788dd576d..66fac6c762 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-11-xx - xxxxxxxxxx - lavfi 8.19.100 - avfilter.h + Add AVFILTER_FLAG_METADATA_ONLY. + 2021-12-03 - xxxxxxxxxx - lavu 57.10.100 - frame.h Add AVFrame.time_base diff --git a/libavfilter/af_acopy.c b/libavfilter/af_acopy.c index 32455d9186..1591ec9639 100644 --- a/libavfilter/af_acopy.c +++ b/libavfilter/af_acopy.c @@ -63,6 +63,7 @@ static const AVFilterPad acopy_outputs[] = { const AVFilter ff_af_acopy = { .name = "acopy", .description = NULL_IF_CONFIG_SMALL("Copy the input audio unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(acopy_inputs), FILTER_OUTPUTS(acopy_outputs), }; diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c index 7e25c0c6a4..ed3c75311a 100644 --- a/libavfilter/af_aformat.c +++ b/libavfilter/af_aformat.c @@ -162,6 +162,7 @@ const AVFilter ff_af_aformat = { .uninit = uninit, .priv_size = sizeof(AFormatContext), .priv_class = &aformat_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_af_aformat_inputs), FILTER_OUTPUTS(avfilter_af_aformat_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_anull.c b/libavfilter/af_anull.c index 065d37e17e..78c5faeb23 100644 --- a/libavfilter/af_anull.c +++ b/libavfilter/af_anull.c @@ -44,6 +44,7 @@ static const AVFilterPad avfilter_af_anull_outputs[] = { const AVFilter ff_af_anull = { .name = "anull", .description = NULL_IF_CONFIG_SMALL("Pass the source unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_af_anull_inputs), FILTER_OUTPUTS(avfilter_af_anull_outputs), }; diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c index 72b6dfa78b..addfe5f158 100644 --- a/libavfilter/af_asdr.c +++ b/libavfilter/af_asdr.c @@ -166,6 +166,7 @@ const AVFilter ff_af_asdr = { .priv_size = sizeof(AudioSDRContext), .activate = activate, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), diff --git a/libavfilter/af_asetrate.c b/libavfilter/af_asetrate.c index 637fa4fbb8..76f29144e5 100644 --- a/libavfilter/af_asetrate.c +++ b/libavfilter/af_asetrate.c @@ -113,4 +113,5 @@ const AVFilter ff_af_asetrate = { FILTER_OUTPUTS(asetrate_outputs), FILTER_QUERY_FUNC(query_formats), .priv_class = &asetrate_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index b6623fa69d..c76756db63 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -257,6 +257,7 @@ const AVFilter ff_af_ashowinfo = { .description = NULL_IF_CONFIG_SMALL("Show textual information for each audio frame."), .priv_size = sizeof(AShowInfoContext), .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; diff --git a/libavfilter/af_asr.c b/libavfilter/af_asr.c index b9c7068526..42250e79e2 100644 --- a/libavfilter/af_asr.c +++ b/libavfilter/af_asr.c @@ -172,6 +172,7 @@ const AVFilter ff_af_asr = { .priv_class = &asr_class, .init = asr_init, .uninit = asr_uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asr_inputs), FILTER_OUTPUTS(asr_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index 3955a4e8e9..d0810b5dd4 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -848,5 +848,5 @@ const AVFilter ff_af_astats = { AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP), - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index 6e0d80a3f1..2021cab143 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -202,6 +202,7 @@ const AVFilter ff_af_drmeter = { .priv_size = sizeof(DRMeterContext), .priv_class = &drmeter_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(drmeter_inputs), FILTER_OUTPUTS(drmeter_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT), diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c index ee0312da82..e9bfc5676c 100644 --- a/libavfilter/af_replaygain.c +++ b/libavfilter/af_replaygain.c @@ -606,6 +606,7 @@ const AVFilter ff_af_replaygain = { .description = NULL_IF_CONFIG_SMALL("ReplayGain scanner."), .uninit = uninit, .priv_size = sizeof(ReplayGainContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(replaygain_inputs), FILTER_OUTPUTS(replaygain_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index fa0884bee8..0ba76469de 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -272,4 +272,5 @@ const AVFilter ff_af_silencedetect = { AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P), .priv_class = &silencedetect_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/af_volumedetect.c b/libavfilter/af_volumedetect.c index c137cc7e50..486fccc4e9 100644 --- a/libavfilter/af_volumedetect.c +++ b/libavfilter/af_volumedetect.c @@ -134,6 +134,7 @@ const AVFilter ff_af_volumedetect = { .description = NULL_IF_CONFIG_SMALL("Detect audio volume."), .priv_size = sizeof(VolDetectContext), .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(volumedetect_inputs), FILTER_OUTPUTS(volumedetect_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P), diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index f7208754a7..b105dc3159 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -119,6 +119,22 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx); * and processing them concurrently. */ #define AVFILTER_FLAG_SLICE_THREADS (1 << 2) +/** + * The filter is a "metadata" filter - it does not modify the frame data in any + * way. It may only affect the metadata (i.e. those fields copied by + * av_frame_copy_props()). + * + * More precisely, this means: + * - video: the data of any frame output by the filter must be exactly equal to + * some frame that is received on one of its inputs. Furthermore, all frames + * produced on a given output must correspond to frames received on the same + * input and their order must be unchanged. Note that the filter may still + * drop or duplicate the frames. + * - audio: the data produced by the filter on any of its outputs (viewed e.g. + * as an array of interleaved samples) must be exactly equal to the data + * received by the filter on one of its inputs. + */ +#define AVFILTER_FLAG_METADATA_ONLY (1 << 3) /** * Some filters support a generic "enable" expression option that can be used * to enable or disable a filter in the timeline. Filters supporting this diff --git a/libavfilter/f_bench.c b/libavfilter/f_bench.c index f7098adaf4..109a530d7c 100644 --- a/libavfilter/f_bench.c +++ b/libavfilter/f_bench.c @@ -113,6 +113,7 @@ const AVFilter ff_vf_bench = { FILTER_INPUTS(bench_inputs), FILTER_OUTPUTS(bench_outputs), .priv_class = &bench_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_BENCH_FILTER */ @@ -143,5 +144,6 @@ const AVFilter ff_af_abench = { FILTER_INPUTS(abench_inputs), FILTER_OUTPUTS(abench_outputs), .priv_class = &abench_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_ABENCH_FILTER */ diff --git a/libavfilter/f_cue.c b/libavfilter/f_cue.c index fd55e4bf5f..d90fe54b9a 100644 --- a/libavfilter/f_cue.c +++ b/libavfilter/f_cue.c @@ -142,6 +142,7 @@ const AVFilter ff_af_acue = { .description = NULL_IF_CONFIG_SMALL("Delay filtering to match a cue."), .priv_class = &cue_acue_class, .priv_size = sizeof(CueContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(acue_inputs), FILTER_OUTPUTS(acue_outputs), .activate = activate, diff --git a/libavfilter/f_latency.c b/libavfilter/f_latency.c index de885ca026..6f16d6677e 100644 --- a/libavfilter/f_latency.c +++ b/libavfilter/f_latency.c @@ -118,7 +118,8 @@ const AVFilter ff_vf_latency = { .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(latency_inputs), FILTER_OUTPUTS(latency_outputs), }; diff --git a/libavfilter/f_metadata.c b/libavfilter/f_metadata.c index cecfe62a9c..5f5091e9b7 100644 --- a/libavfilter/f_metadata.c +++ b/libavfilter/f_metadata.c @@ -391,7 +391,8 @@ const AVFilter ff_af_ametadata = { .uninit = uninit, FILTER_INPUTS(ainputs), FILTER_OUTPUTS(aoutputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_AMETADATA_FILTER */ @@ -424,6 +425,7 @@ const AVFilter ff_vf_metadata = { .uninit = uninit, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_METADATA_FILTER */ diff --git a/libavfilter/f_perms.c b/libavfilter/f_perms.c index 470db45bee..6e75b2517b 100644 --- a/libavfilter/f_perms.c +++ b/libavfilter/f_perms.c @@ -138,7 +138,8 @@ const AVFilter ff_af_aperms = { .priv_size = sizeof(PermsContext), FILTER_INPUTS(aperms_inputs), FILTER_OUTPUTS(aperms_outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_APERMS_FILTER */ @@ -167,6 +168,7 @@ const AVFilter ff_vf_perms = { FILTER_INPUTS(perms_inputs), FILTER_OUTPUTS(perms_outputs), .priv_class = &perms_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_PERMS_FILTER */ diff --git a/libavfilter/f_realtime.c b/libavfilter/f_realtime.c index 11bdb058ed..9a60ded0ca 100644 --- a/libavfilter/f_realtime.c +++ b/libavfilter/f_realtime.c @@ -95,6 +95,7 @@ const AVFilter ff_vf_realtime = { .description = NULL_IF_CONFIG_SMALL("Slow down filtering to match realtime."), .priv_size = sizeof(RealtimeContext), .priv_class = &realtime_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_realtime_inputs), FILTER_OUTPUTS(avfilter_vf_realtime_outputs), }; @@ -122,6 +123,7 @@ const AVFilter ff_af_arealtime = { .description = NULL_IF_CONFIG_SMALL("Slow down filtering to match realtime."), .priv_class = &realtime_class, .priv_size = sizeof(RealtimeContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(arealtime_inputs), FILTER_OUTPUTS(arealtime_outputs), }; diff --git a/libavfilter/f_segment.c b/libavfilter/f_segment.c index 70c8393972..5f44634803 100644 --- a/libavfilter/f_segment.c +++ b/libavfilter/f_segment.c @@ -286,7 +286,7 @@ const AVFilter ff_vf_segment = { .activate = activate, FILTER_INPUTS(segment_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; #endif // CONFIG_SEGMENT_FILTER @@ -325,6 +325,6 @@ const AVFilter ff_af_asegment = { .activate = activate, FILTER_INPUTS(asegment_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; #endif // CONFIG_ASEGMENT_FILTER diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index 47e7d1fef8..b61d88f4fe 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -533,6 +533,6 @@ const AVFilter ff_vf_select = { .priv_class = &select_class, FILTER_INPUTS(avfilter_vf_select_inputs), FILTER_QUERY_FUNC(query_formats), - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_SELECT_FILTER */ diff --git a/libavfilter/f_sendcmd.c b/libavfilter/f_sendcmd.c index f71d211eb4..7261a05aae 100644 --- a/libavfilter/f_sendcmd.c +++ b/libavfilter/f_sendcmd.c @@ -597,6 +597,7 @@ const AVFilter ff_vf_sendcmd = { .init = init, .uninit = uninit, .priv_size = sizeof(SendCmdContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(sendcmd_inputs), FILTER_OUTPUTS(sendcmd_outputs), .priv_class = &sendcmd_class, @@ -628,6 +629,7 @@ const AVFilter ff_af_asendcmd = { .init = init, .uninit = uninit, .priv_size = sizeof(SendCmdContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asendcmd_inputs), FILTER_OUTPUTS(asendcmd_outputs), }; diff --git a/libavfilter/f_sidedata.c b/libavfilter/f_sidedata.c index 5c9f905cc2..8eccd4a06e 100644 --- a/libavfilter/f_sidedata.c +++ b/libavfilter/f_sidedata.c @@ -147,7 +147,8 @@ const AVFilter ff_af_asidedata = { .init = init, FILTER_INPUTS(ainputs), FILTER_OUTPUTS(aoutputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_ASIDEDATA_FILTER */ @@ -179,6 +180,7 @@ const AVFilter ff_vf_sidedata = { .init = init, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_SIDEDATA_FILTER */ diff --git a/libavfilter/fifo.c b/libavfilter/fifo.c index bb7d78f09c..1c7be88ae1 100644 --- a/libavfilter/fifo.c +++ b/libavfilter/fifo.c @@ -132,6 +132,7 @@ const AVFilter ff_vf_fifo = { .init = init, .uninit = uninit, .priv_size = sizeof(FifoContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_fifo_inputs), FILTER_OUTPUTS(avfilter_vf_fifo_outputs), }; @@ -158,6 +159,7 @@ const AVFilter ff_af_afifo = { .init = init, .uninit = uninit, .priv_size = sizeof(FifoContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_af_afifo_inputs), FILTER_OUTPUTS(avfilter_af_afifo_outputs), }; diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index fad92033e4..054feb05f1 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -294,6 +294,7 @@ const AVFilter ff_vf_setpts = { .init = init, .activate = activate, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, .priv_size = sizeof(SetPTSContext), .priv_class = &setpts_class, @@ -334,6 +335,7 @@ const AVFilter ff_af_asetpts = { .uninit = uninit, .priv_size = sizeof(SetPTSContext), .priv_class = &asetpts_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asetpts_inputs), FILTER_OUTPUTS(asetpts_outputs), }; diff --git a/libavfilter/settb.c b/libavfilter/settb.c index ae2cf9b888..67d310afbd 100644 --- a/libavfilter/settb.c +++ b/libavfilter/settb.c @@ -185,6 +185,7 @@ const AVFilter ff_vf_settb = { FILTER_INPUTS(avfilter_vf_settb_inputs), FILTER_OUTPUTS(avfilter_vf_settb_outputs), .activate = activate, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_SETTB_FILTER */ @@ -216,5 +217,6 @@ const AVFilter ff_af_asettb = { FILTER_OUTPUTS(avfilter_af_asettb_outputs), .priv_class = &asettb_class, .activate = activate, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_ASETTB_FILTER */ diff --git a/libavfilter/split.c b/libavfilter/split.c index a08ddf72b1..6b9b656708 100644 --- a/libavfilter/split.c +++ b/libavfilter/split.c @@ -112,7 +112,7 @@ const AVFilter ff_vf_split = { .init = split_init, FILTER_INPUTS(avfilter_vf_split_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; static const AVFilterPad avfilter_af_asplit_inputs[] = { @@ -131,5 +131,5 @@ const AVFilter ff_af_asplit = { .init = split_init, FILTER_INPUTS(avfilter_af_asplit_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/trim.c b/libavfilter/trim.c index c260da3a0b..e627903c64 100644 --- a/libavfilter/trim.c +++ b/libavfilter/trim.c @@ -363,6 +363,7 @@ const AVFilter ff_af_atrim = { .init = init, .priv_size = sizeof(TrimContext), .priv_class = &atrim_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(atrim_inputs), FILTER_OUTPUTS(atrim_outputs), }; diff --git a/libavfilter/version.h b/libavfilter/version.h index e0bdcb836d..0247fb4f9a 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 18 +#define LIBAVFILTER_VERSION_MINOR 19 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_addroi.c b/libavfilter/vf_addroi.c index 5f9ec21754..dd3daeda81 100644 --- a/libavfilter/vf_addroi.c +++ b/libavfilter/vf_addroi.c @@ -262,6 +262,8 @@ const AVFilter ff_vf_addroi = { .priv_size = sizeof(AddROIContext), .priv_class = &addroi_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_INPUTS(addroi_inputs), FILTER_OUTPUTS(addroi_outputs), }; diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 995c7f4f14..2d1eaa954b 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -188,6 +188,7 @@ const AVFilter ff_vf_setdar = { .description = NULL_IF_CONFIG_SMALL("Set the frame display aspect ratio."), .priv_size = sizeof(AspectContext), .priv_class = &setdar_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_setdar_inputs), FILTER_OUTPUTS(avfilter_vf_setdar_outputs), }; @@ -250,6 +251,7 @@ const AVFilter ff_vf_setsar = { .description = NULL_IF_CONFIG_SMALL("Set the pixel sample aspect ratio."), .priv_size = sizeof(AspectContext), .priv_class = &setsar_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_setsar_inputs), FILTER_OUTPUTS(avfilter_vf_setsar_outputs), }; diff --git a/libavfilter/vf_bbox.c b/libavfilter/vf_bbox.c index 559ca505bf..02893d500d 100644 --- a/libavfilter/vf_bbox.c +++ b/libavfilter/vf_bbox.c @@ -151,6 +151,6 @@ const AVFilter ff_vf_bbox = { FILTER_INPUTS(bbox_inputs), FILTER_OUTPUTS(bbox_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c index 93d5b077f1..99ff1ac606 100644 --- a/libavfilter/vf_blackdetect.c +++ b/libavfilter/vf_blackdetect.c @@ -257,5 +257,5 @@ const AVFilter ff_vf_blackdetect = { FILTER_PIXFMTS_ARRAY(pix_fmts), .uninit = uninit, .priv_class = &blackdetect_class, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index d37b3f3c13..e5e185dbea 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -127,6 +127,7 @@ const AVFilter ff_vf_blackframe = { .description = NULL_IF_CONFIG_SMALL("Detect frames that are (almost) black."), .priv_size = sizeof(BlackFrameContext), .priv_class = &blackframe_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_blackframe_inputs), FILTER_OUTPUTS(avfilter_vf_blackframe_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_copy.c b/libavfilter/vf_copy.c index 5554565bae..2fbced354f 100644 --- a/libavfilter/vf_copy.c +++ b/libavfilter/vf_copy.c @@ -75,6 +75,7 @@ static const AVFilterPad avfilter_vf_copy_outputs[] = { const AVFilter ff_vf_copy = { .name = "copy", .description = NULL_IF_CONFIG_SMALL("Copy the input video unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_copy_inputs), FILTER_OUTPUTS(avfilter_vf_copy_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index af3a8f333f..b887b9ecb1 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -273,5 +273,5 @@ const AVFilter ff_vf_cropdetect = { FILTER_INPUTS(avfilter_vf_cropdetect_inputs), FILTER_OUTPUTS(avfilter_vf_cropdetect_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_entropy.c b/libavfilter/vf_entropy.c index 16569682a9..893d07d8e6 100644 --- a/libavfilter/vf_entropy.c +++ b/libavfilter/vf_entropy.c @@ -192,5 +192,5 @@ const AVFilter ff_vf_entropy = { FILTER_OUTPUTS(outputs), FILTER_PIXFMTS_ARRAY(pixfmts), .priv_class = &entropy_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_find_rect.c b/libavfilter/vf_find_rect.c index 6ac714ce45..a536d669d1 100644 --- a/libavfilter/vf_find_rect.c +++ b/libavfilter/vf_find_rect.c @@ -294,6 +294,7 @@ const AVFilter ff_vf_find_rect = { .priv_size = sizeof(FOCContext), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(foc_inputs), FILTER_OUTPUTS(foc_outputs), FILTER_PIXFMTS(AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P), diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c index 7e15c43086..c78acbf87b 100644 --- a/libavfilter/vf_format.c +++ b/libavfilter/vf_format.c @@ -169,6 +169,8 @@ const AVFilter ff_vf_format = { .priv_size = sizeof(FormatContext), .priv_class = &format_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_INPUTS(avfilter_vf_format_inputs), FILTER_OUTPUTS(avfilter_vf_format_outputs), @@ -203,6 +205,8 @@ const AVFilter ff_vf_noformat = { .priv_size = sizeof(FormatContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_INPUTS(avfilter_vf_noformat_inputs), FILTER_OUTPUTS(avfilter_vf_noformat_outputs), diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index b8714727fa..99e679441e 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -388,6 +388,7 @@ const AVFilter ff_vf_fps = { .priv_size = sizeof(FPSContext), .priv_class = &fps_class, .activate = activate, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_fps_inputs), FILTER_OUTPUTS(avfilter_vf_fps_outputs), }; diff --git a/libavfilter/vf_framestep.c b/libavfilter/vf_framestep.c index 5509df53e9..b8eee53b59 100644 --- a/libavfilter/vf_framestep.c +++ b/libavfilter/vf_framestep.c @@ -94,5 +94,5 @@ const AVFilter ff_vf_framestep = { .priv_class = &framestep_class, FILTER_INPUTS(framestep_inputs), FILTER_OUTPUTS(framestep_outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_freezedetect.c b/libavfilter/vf_freezedetect.c index 99f0aae5a2..31a80a6dc0 100644 --- a/libavfilter/vf_freezedetect.c +++ b/libavfilter/vf_freezedetect.c @@ -217,6 +217,7 @@ const AVFilter ff_vf_freezedetect = { .priv_size = sizeof(FreezeDetectContext), .priv_class = &freezedetect_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(freezedetect_inputs), FILTER_OUTPUTS(freezedetect_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_identity.c b/libavfilter/vf_identity.c index 5096bda382..cc30761388 100644 --- a/libavfilter/vf_identity.c +++ b/libavfilter/vf_identity.c @@ -412,7 +412,9 @@ const AVFilter ff_vf_identity = { FILTER_INPUTS(identity_inputs), FILTER_OUTPUTS(identity_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_IDENTITY_FILTER */ @@ -434,7 +436,9 @@ const AVFilter ff_vf_msad = { FILTER_INPUTS(identity_inputs), FILTER_OUTPUTS(identity_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_MSAD_FILTER */ diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 0f3e78c4ec..9320b485d8 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -436,6 +436,7 @@ const AVFilter ff_vf_idet = { .priv_size = sizeof(IDETContext), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(idet_inputs), FILTER_OUTPUTS(idet_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_mestimate.c b/libavfilter/vf_mestimate.c index d8bcfdde02..eff58f612e 100644 --- a/libavfilter/vf_mestimate.c +++ b/libavfilter/vf_mestimate.c @@ -363,6 +363,7 @@ const AVFilter ff_vf_mestimate = { .priv_size = sizeof(MEContext), .priv_class = &mestimate_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(mestimate_inputs), FILTER_OUTPUTS(mestimate_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_null.c b/libavfilter/vf_null.c index 33b1185ce0..fa80e2a102 100644 --- a/libavfilter/vf_null.c +++ b/libavfilter/vf_null.c @@ -43,6 +43,7 @@ static const AVFilterPad avfilter_vf_null_outputs[] = { const AVFilter ff_vf_null = { .name = "null", .description = NULL_IF_CONFIG_SMALL("Pass the source unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_null_inputs), FILTER_OUTPUTS(avfilter_vf_null_outputs), }; diff --git a/libavfilter/vf_ocr.c b/libavfilter/vf_ocr.c index f6249e61fc..1648afa0f9 100644 --- a/libavfilter/vf_ocr.c +++ b/libavfilter/vf_ocr.c @@ -143,6 +143,7 @@ const AVFilter ff_vf_ocr = { .priv_class = &ocr_class, .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(ocr_inputs), FILTER_OUTPUTS(ocr_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c index f96179db44..19852eaa69 100644 --- a/libavfilter/vf_psnr.c +++ b/libavfilter/vf_psnr.c @@ -466,5 +466,7 @@ const AVFilter ff_vf_psnr = { FILTER_INPUTS(psnr_inputs), FILTER_OUTPUTS(psnr_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c index d942ba1579..7c9d60fe21 100644 --- a/libavfilter/vf_qp.c +++ b/libavfilter/vf_qp.c @@ -198,5 +198,6 @@ const AVFilter ff_vf_qp = { FILTER_INPUTS(qp_inputs), FILTER_OUTPUTS(qp_outputs), .priv_class = &qp_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_readeia608.c b/libavfilter/vf_readeia608.c index b9dc46e10e..a5a0249fb7 100644 --- a/libavfilter/vf_readeia608.c +++ b/libavfilter/vf_readeia608.c @@ -555,6 +555,8 @@ const AVFilter ff_vf_readeia608 = { FILTER_OUTPUTS(readeia608_outputs), FILTER_PIXFMTS_ARRAY(pixel_fmts), .uninit = uninit, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, .process_command = process_command, }; diff --git a/libavfilter/vf_readvitc.c b/libavfilter/vf_readvitc.c index 370cf5d15d..d0fba234f7 100644 --- a/libavfilter/vf_readvitc.c +++ b/libavfilter/vf_readvitc.c @@ -242,6 +242,7 @@ const AVFilter ff_vf_readvitc = { .description = NULL_IF_CONFIG_SMALL("Read vertical interval timecode and write it to frame metadata."), .priv_size = sizeof(ReadVitcContext), .priv_class = &readvitc_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_PIXFMTS_ARRAY(pixel_fmts), diff --git a/libavfilter/vf_scdet.c b/libavfilter/vf_scdet.c index d11d2e2e2c..1576759c24 100644 --- a/libavfilter/vf_scdet.c +++ b/libavfilter/vf_scdet.c @@ -206,6 +206,7 @@ const AVFilter ff_vf_scdet = { .priv_size = sizeof(SCDetContext), .priv_class = &scdet_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(scdet_inputs), FILTER_OUTPUTS(scdet_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c index 0a79599bab..b3893adc13 100644 --- a/libavfilter/vf_setparams.c +++ b/libavfilter/vf_setparams.c @@ -165,6 +165,7 @@ const AVFilter ff_vf_setparams = { .description = NULL_IF_CONFIG_SMALL("Force field, or color property for the output video frame."), .priv_size = sizeof(SetParamsContext), .priv_class = &setparams_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; @@ -204,6 +205,7 @@ const AVFilter ff_vf_setrange = { .priv_size = sizeof(SetParamsContext), .init = init_setrange, .priv_class = &setrange_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; @@ -238,6 +240,7 @@ const AVFilter ff_vf_setfield = { .priv_size = sizeof(SetParamsContext), .init = init_setfield, .priv_class = &setfield_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index ff438e70c6..62c7833247 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -678,4 +678,5 @@ const AVFilter ff_vf_showinfo = { FILTER_OUTPUTS(avfilter_vf_showinfo_outputs), .priv_size = sizeof(ShowInfoContext), .priv_class = &showinfo_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c index c6989d618b..32f313817d 100644 --- a/libavfilter/vf_ssim.c +++ b/libavfilter/vf_ssim.c @@ -592,5 +592,7 @@ const AVFilter ff_vf_ssim = { FILTER_INPUTS(ssim_inputs), FILTER_OUTPUTS(ssim_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_vfrdet.c b/libavfilter/vf_vfrdet.c index fda8c2d485..0ca221b5b8 100644 --- a/libavfilter/vf_vfrdet.c +++ b/libavfilter/vf_vfrdet.c @@ -108,6 +108,7 @@ const AVFilter ff_vf_vfrdet = { .priv_size = sizeof(VFRDETContext), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(vfrdet_inputs), FILTER_OUTPUTS(vfrdet_outputs), }; diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c index 05c95d0eeb..267a62ea9b 100644 --- a/libavfilter/vf_vidstabdetect.c +++ b/libavfilter/vf_vidstabdetect.c @@ -196,6 +196,7 @@ const AVFilter ff_vf_vidstabdetect = { .priv_size = sizeof(StabData), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_vidstabdetect_inputs), FILTER_OUTPUTS(avfilter_vf_vidstabdetect_outputs), FILTER_PIXFMTS_ARRAY(ff_vidstab_pix_fmts), diff --git a/libavfilter/vf_vif.c b/libavfilter/vf_vif.c index 09854641b1..818cc51e36 100644 --- a/libavfilter/vf_vif.c +++ b/libavfilter/vf_vif.c @@ -638,5 +638,7 @@ const AVFilter ff_vf_vif = { FILTER_INPUTS(vif_inputs), FILTER_OUTPUTS(vif_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_vmafmotion.c b/libavfilter/vf_vmafmotion.c index 362839735e..8b7e9b17ef 100644 --- a/libavfilter/vf_vmafmotion.c +++ b/libavfilter/vf_vmafmotion.c @@ -363,6 +363,7 @@ const AVFilter ff_vf_vmafmotion = { .uninit = uninit, .priv_size = sizeof(VMAFMotionContext), .priv_class = &vmafmotion_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(vmafmotion_inputs), FILTER_OUTPUTS(vmafmotion_outputs), FILTER_QUERY_FUNC(query_formats), From 425889396137451ae30288c84122e28532b71596 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 Nov 2021 10:18:01 +0100 Subject: [PATCH 369/894] ffmpeg: make -bits_per_raw_sample a per-output-stream option Also, document it and make it apply to audio in addition to video. --- doc/ffmpeg.texi | 7 +++++++ fftools/ffmpeg.c | 11 +++++++---- fftools/ffmpeg.h | 3 +++ fftools/ffmpeg_opt.c | 11 +++++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 082eba5f14..20a547381c 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1960,6 +1960,13 @@ filter (scale, aresample) in the graph. On by default, to explicitly disable it you need to specify @code{-noauto_conversion_filters}. +@item -bits_per_raw_sample[:@var{stream_specifier}] @var{value} (@emph{output,per-stream}) +Declare the number of bits per raw sample in the given output stream to be +@var{value}. Note that this option sets the information provided to the +encoder/muxer, it does not change the stream to conform to this value. Setting +values that do not match the stream properties may result in encoding failures +or invalid output files. + @end table @section Preset files diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index cfb04d5eff..03aec1af11 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3329,13 +3329,16 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) switch (enc_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); - if (dec_ctx) - enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, - av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); enc_ctx->channel_layout = av_buffersink_get_channel_layout(ost->filter->filter); enc_ctx->channels = av_buffersink_get_channels(ost->filter->filter); + if (ost->bits_per_raw_sample) + enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; + else if (dec_ctx) + enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); + init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); break; @@ -3378,7 +3381,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) enc_ctx->width != dec_ctx->width || enc_ctx->height != dec_ctx->height || enc_ctx->pix_fmt != dec_ctx->pix_fmt) { - enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample; + enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; } // Field order: autodetection diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index a20ca964fb..c14eed5643 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -228,6 +228,8 @@ typedef struct OptionsContext { int nb_enc_time_bases; SpecifierOpt *autoscale; int nb_autoscale; + SpecifierOpt *bits_per_raw_sample; + int nb_bits_per_raw_sample; } OptionsContext; typedef struct InputFilter { @@ -483,6 +485,7 @@ typedef struct OutputStream { int top_field_first; int rotate_overridden; int autoscale; + int bits_per_raw_sample; double rotate_override_value; AVRational frame_aspect_ratio; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index a27263b879..6c2eb53290 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -96,6 +96,7 @@ static const char *const opt_name_discard[] = {"discard", NULL static const char *const opt_name_disposition[] = {"disposition", NULL}; static const char *const opt_name_time_bases[] = {"time_base", NULL}; static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL}; +static const char *const opt_name_bits_per_raw_sample[] = {"bits_per_raw_sample", NULL}; #define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\ {\ @@ -160,7 +161,6 @@ int abort_on_flags = 0; int print_stats = -1; int qp_hist = 0; int stdin_interaction = 1; -int frame_bits_per_raw_sample = 0; float max_error_rate = 2.0/3; char *filter_nbthreads; int filter_complex_nbthreads = 0; @@ -1604,6 +1604,9 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->muxing_queue_data_threshold = 50*1024*1024; MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); + MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, + oc, st); + if (oc->oformat->flags & AVFMT_GLOBALHEADER) ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -1769,7 +1772,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in exit_program(1); } - video_enc->bits_per_raw_sample = frame_bits_per_raw_sample; MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); if (frame_pix_fmt && *frame_pix_fmt == '+') { ost->keep_pix_fmt = 1; @@ -3681,6 +3683,9 @@ const OptionDef options[] = { "set the maximum number of queued packets from the demuxer" }, { "find_stream_info", OPT_BOOL | OPT_PERFILE | OPT_INPUT | OPT_EXPERT, { &find_stream_info }, "read and decode the streams to fill missing information with heuristics" }, + { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, + { .off = OFFSET(bits_per_raw_sample) }, + "set the number of bits per raw sample", "number" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -3700,8 +3705,6 @@ const OptionDef options[] = { { "pix_fmt", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_pix_fmts) }, "set pixel format", "format" }, - { "bits_per_raw_sample", OPT_VIDEO | OPT_INT | HAS_ARG, { &frame_bits_per_raw_sample }, - "set the number of bits per raw sample", "number" }, { "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) }, "disable video" }, { "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | From ab3ef54c8c6a47576a07ecdaacbc0b0096374f4a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 Nov 2021 11:22:57 +0100 Subject: [PATCH 370/894] ffmpeg: only copy bits_per_sample from decoder when it remains valid I.e. when the only filters that are applied do not modify the frame data. --- fftools/ffmpeg.c | 14 +++++--------- fftools/ffmpeg.h | 3 +++ fftools/ffmpeg_filter.c | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 03aec1af11..47e6a8683e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3335,7 +3335,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (ost->bits_per_raw_sample) enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; - else if (dec_ctx) + else if (dec_ctx && ost->filter->graph->is_meta) enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); @@ -3361,7 +3361,10 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) av_buffersink_get_sample_aspect_ratio(ost->filter->filter); enc_ctx->pix_fmt = av_buffersink_get_format(ost->filter->filter); - if (dec_ctx) + + if (ost->bits_per_raw_sample) + enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; + else if (dec_ctx && ost->filter->graph->is_meta) enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); @@ -3377,13 +3380,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->st->avg_frame_rate = ost->frame_rate; - if (!dec_ctx || - enc_ctx->width != dec_ctx->width || - enc_ctx->height != dec_ctx->height || - enc_ctx->pix_fmt != dec_ctx->pix_fmt) { - enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; - } - // Field order: autodetection if (frame) { if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c14eed5643..cc7ba9bdca 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -287,6 +287,9 @@ typedef struct FilterGraph { AVFilterGraph *graph; int reconfiguration; + // true when the filtergraph contains only meta filters + // that do not modify the frame data + int is_meta; InputFilter **inputs; int nb_inputs; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index dab0f28819..22bfdc572d 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -960,6 +960,30 @@ static void cleanup_filtergraph(FilterGraph *fg) avfilter_graph_free(&fg->graph); } +static int filter_is_buffersrc(const AVFilterContext *f) +{ + return f->nb_inputs == 0 && + (!strcmp(f->filter->name, "buffersrc") || + !strcmp(f->filter->name, "abuffersrc")); +} + +static int graph_is_meta(AVFilterGraph *graph) +{ + for (unsigned i = 0; i < graph->nb_filters; i++) { + const AVFilterContext *f = graph->filters[i]; + + /* in addition to filters flagged as meta, also + * disregard sinks and buffersources (but not other sources, + * since they introduce data we are not aware of) + */ + if (!((f->filter->flags & AVFILTER_FLAG_METADATA_ONLY) || + f->nb_outputs == 0 || + filter_is_buffersrc(f))) + return 0; + } + return 1; +} + int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; @@ -1060,6 +1084,8 @@ int configure_filtergraph(FilterGraph *fg) if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) goto fail; + fg->is_meta = graph_is_meta(fg->graph); + /* limit the lists of allowed formats to the ones selected, to * make sure they stay the same if the filtergraph is reconfigured later */ for (i = 0; i < fg->nb_outputs; i++) { From 2755e6f32a51205117239b3b4a8e5fd6ebbf9db0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 17:26:10 +0100 Subject: [PATCH 371/894] doc/APIchanges: fix typo --- doc/APIchanges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 66fac6c762..2914ad6734 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -33,7 +33,7 @@ API changes, most recent first: Add "disposition" AVOption to AVStream's class. 2021-11-12 - xxxxxxxxxx - lavu 57.8.100 - hwcontext_vulkan.h - Added AVFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, + Added AVVkFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, nb_encode_queues, queue_family_decode_index, and nb_decode_queues. 2021-10-18 - xxxxxxxxxx - lavf 59.8.100 - avio.h From 3b8efec3c58ab1e30d72427d3025a0641b442f71 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 16:29:54 +0100 Subject: [PATCH 372/894] lavu/frame: drop mentions of non-refcounted frames All frames we deal with should always be refcounted now. --- libavutil/frame.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libavutil/frame.h b/libavutil/frame.h index 882b5afbde..933944526d 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -314,6 +314,9 @@ typedef struct AVFrame { * This might be different from the first allocated byte. For video, * it could even point to the end of the image data. * + * All pointers in data and extended_data must point into one of the + * AVBufferRef in buf or extended_buf. + * * Some decoders access areas outside 0,0 - width,height, please * see avcodec_align_dimensions2(). Some filters and swscale can read * up to 16 bytes beyond the planes, if these filters are to be used, @@ -490,10 +493,10 @@ typedef struct AVFrame { uint64_t channel_layout; /** - * AVBuffer references backing the data for this frame. If all elements of - * this array are NULL, then this frame is not reference counted. This array - * must be filled contiguously -- if buf[i] is non-NULL then buf[j] must - * also be non-NULL for all j < i. + * AVBuffer references backing the data for this frame. All the pointers in + * data and extended_data must point inside one of the buffers in buf or + * extended_buf. This array must be filled contiguously -- if buf[i] is + * non-NULL then buf[j] must also be non-NULL for all j < i. * * There may be at most one AVBuffer per data plane, so for video this array * always contains all the references. For planar audio with more than From 3a9861e22c636d843c10e23f5585196d1f3400dd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 16:31:30 +0100 Subject: [PATCH 373/894] lavu/frame: clarify doxy AVFrame.data[] elements not used by the format should ALWAYS be null, hwaccel formats are not an exception. --- libavutil/frame.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavutil/frame.h b/libavutil/frame.h index 933944526d..3f295f6b9e 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -322,8 +322,7 @@ typedef struct AVFrame { * up to 16 bytes beyond the planes, if these filters are to be used, * then 16 extra bytes must be allocated. * - * NOTE: Except for hwaccel formats, pointers not needed by the format - * MUST be set to NULL. + * NOTE: Pointers not needed by the format MUST be set to NULL. * * @attention In case of video, the data[] pointers can point to the * end of image data in order to reverse line order, when used in From 3ca1e31e63085ab84bc2d031c9ba06ea161188d3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 13:12:39 +0100 Subject: [PATCH 374/894] fftools/cmdutils: Atomically add elements to list of pointers, fix crash Currently, adding a (separately allocated) element to a list of pointers works by first reallocating the array of pointers and (on success) incrementing its size and only then allocating the new element. If the latter allocation fails, the size is inconsistent, i.e. array[nb_array_elems - 1] is NULL. Our cleanup code crashes in such scenarios. Fix this by adding an auxiliary function that atomically allocates and adds a new element to a list of pointers. Signed-off-by: Andreas Rheinhardt --- fftools/cmdutils.c | 16 ++++++++++++++++ fftools/cmdutils.h | 17 +++++++++++++++++ fftools/ffmpeg_filter.c | 17 ++++------------- fftools/ffmpeg_opt.c | 22 ++++++---------------- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 45322f8c71..1464b122df 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2214,6 +2214,22 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) return array; } +void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) +{ + void *new_elem, **array = (void**)ptr; + + if (*nb_elems == INT_MAX) { + av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); + exit_program(1); + } + new_elem = av_mallocz(elem_size); + if (!new_elem) + exit_program(1); + GROW_ARRAY(array, *nb_elems); + array[*nb_elems - 1] = new_elem; + return array; +} + double get_rotation(int32_t *displaymatrix) { double theta = 0; diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 64dd7266bc..ae78e60f4c 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -628,11 +628,28 @@ FILE *get_preset_file(char *filename, size_t filename_size, */ void *grow_array(void *array, int elem_size, int *size, int new_size); +/** + * Atomically add a new element to an array of pointers, i.e. allocate + * a new entry, reallocate the array of pointers and make the new last + * member of this array point to the newly allocated buffer. + * Calls exit() on failure. + * + * @param array array of pointers to reallocate + * @param elem_size size of the new element to allocate + * @param nb_elems pointer to the number of elements of the array array; + * *nb_elems will be incremented by one by this function. + * @return reallocated array + */ +void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); + #define media_type_string av_get_media_type_string #define GROW_ARRAY(array, nb_elems)\ array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) +#define ALLOC_ARRAY_ELEM(array, nb_elems)\ + array = allocate_array_elem(array, sizeof(*array[0]), &nb_elems) + #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 22bfdc572d..28704203b9 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -164,18 +164,14 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) exit_program(1); fg->index = nb_filtergraphs; - GROW_ARRAY(fg->outputs, fg->nb_outputs); - if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0])))) - exit_program(1); + ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); fg->outputs[0]->ost = ost; fg->outputs[0]->graph = fg; fg->outputs[0]->format = -1; ost->filter = fg->outputs[0]; - GROW_ARRAY(fg->inputs, fg->nb_inputs); - if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0])))) - exit_program(1); + ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); fg->inputs[0]->ist = ist; fg->inputs[0]->graph = fg; fg->inputs[0]->format = -1; @@ -280,9 +276,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->decoding_needed |= DECODING_FOR_FILTER; ist->st->discard = AVDISCARD_NONE; - GROW_ARRAY(fg->inputs, fg->nb_inputs); - if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0])))) - exit_program(1); + ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); fg->inputs[fg->nb_inputs - 1]->ist = ist; fg->inputs[fg->nb_inputs - 1]->graph = fg; fg->inputs[fg->nb_inputs - 1]->format = -1; @@ -318,10 +312,7 @@ int init_complex_filtergraph(FilterGraph *fg) init_input_filter(fg, cur); for (cur = outputs; cur;) { - GROW_ARRAY(fg->outputs, fg->nb_outputs); - fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])); - if (!fg->outputs[fg->nb_outputs - 1]) - exit_program(1); + ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); fg->outputs[fg->nb_outputs - 1]->graph = fg; fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 6c2eb53290..848b817e9c 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1265,11 +1265,8 @@ static int open_input_file(OptionsContext *o, const char *filename) /* dump the file content */ av_dump_format(ic, nb_input_files, filename, 0); - GROW_ARRAY(input_files, nb_input_files); - f = av_mallocz(sizeof(*f)); - if (!f) - exit_program(1); - input_files[nb_input_files - 1] = f; + ALLOC_ARRAY_ELEM(input_files, nb_input_files); + f = input_files[nb_input_files - 1]; f->ctx = ic; f->ist_index = nb_input_streams - ic->nb_streams; @@ -2263,11 +2260,8 @@ static int open_output_file(OptionsContext *o, const char *filename) } } - GROW_ARRAY(output_files, nb_output_files); - of = av_mallocz(sizeof(*of)); - if (!of) - exit_program(1); - output_files[nb_output_files - 1] = of; + ALLOC_ARRAY_ELEM(output_files, nb_output_files); + of = output_files[nb_output_files - 1]; of->ost_index = nb_output_streams; of->recording_time = o->recording_time; @@ -3264,9 +3258,7 @@ static int opt_audio_qscale(void *optctx, const char *opt, const char *arg) static int opt_filter_complex(void *optctx, const char *opt, const char *arg) { - GROW_ARRAY(filtergraphs, nb_filtergraphs); - if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) - return AVERROR(ENOMEM); + ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg); if (!filtergraphs[nb_filtergraphs - 1]->graph_desc) @@ -3283,9 +3275,7 @@ static int opt_filter_complex_script(void *optctx, const char *opt, const char * if (!graph_desc) return AVERROR(EINVAL); - GROW_ARRAY(filtergraphs, nb_filtergraphs); - if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) - return AVERROR(ENOMEM); + ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc; From 9d73967b40231b27504cb86ea177887be03bb328 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 13:38:48 +0100 Subject: [PATCH 375/894] fftools/ffmpeg_(filter|opt): Use dedicated pointer for array elem access Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_filter.c | 54 +++++++++++++++++++++++------------------ fftools/ffmpeg_opt.c | 14 +++++++---- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 28704203b9..7263ea5f03 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -159,29 +159,33 @@ DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0, int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { FilterGraph *fg = av_mallocz(sizeof(*fg)); + OutputFilter *ofilter; + InputFilter *ifilter; if (!fg) exit_program(1); fg->index = nb_filtergraphs; ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); - fg->outputs[0]->ost = ost; - fg->outputs[0]->graph = fg; - fg->outputs[0]->format = -1; + ofilter = fg->outputs[0]; + ofilter->ost = ost; + ofilter->graph = fg; + ofilter->format = -1; - ost->filter = fg->outputs[0]; + ost->filter = ofilter; ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); - fg->inputs[0]->ist = ist; - fg->inputs[0]->graph = fg; - fg->inputs[0]->format = -1; + ifilter = fg->inputs[0]; + ifilter->ist = ist; + ifilter->graph = fg; + ifilter->format = -1; - fg->inputs[0]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); - if (!fg->inputs[0]->frame_queue) + ifilter->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!ifilter->frame_queue) exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); - ist->filters[ist->nb_filters - 1] = fg->inputs[0]; + ist->filters[ist->nb_filters - 1] = ifilter; GROW_ARRAY(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1] = fg; @@ -210,6 +214,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) { InputStream *ist = NULL; enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); + InputFilter *ifilter; int i; // TODO: support other filter types @@ -277,18 +282,19 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->st->discard = AVDISCARD_NONE; ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); - fg->inputs[fg->nb_inputs - 1]->ist = ist; - fg->inputs[fg->nb_inputs - 1]->graph = fg; - fg->inputs[fg->nb_inputs - 1]->format = -1; - fg->inputs[fg->nb_inputs - 1]->type = ist->st->codecpar->codec_type; - fg->inputs[fg->nb_inputs - 1]->name = describe_filter_link(fg, in, 1); + ifilter = fg->inputs[fg->nb_inputs - 1]; + ifilter->ist = ist; + ifilter->graph = fg; + ifilter->format = -1; + ifilter->type = ist->st->codecpar->codec_type; + ifilter->name = describe_filter_link(fg, in, 1); - fg->inputs[fg->nb_inputs - 1]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); - if (!fg->inputs[fg->nb_inputs - 1]->frame_queue) + ifilter->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!ifilter->frame_queue) exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); - ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; + ist->filters[ist->nb_filters - 1] = ifilter; } int init_complex_filtergraph(FilterGraph *fg) @@ -312,15 +318,17 @@ int init_complex_filtergraph(FilterGraph *fg) init_input_filter(fg, cur); for (cur = outputs; cur;) { + OutputFilter *ofilter; ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); + ofilter = fg->outputs[fg->nb_outputs - 1]; - fg->outputs[fg->nb_outputs - 1]->graph = fg; - fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; - fg->outputs[fg->nb_outputs - 1]->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, + ofilter->graph = fg; + ofilter->out_tmp = cur; + ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); - fg->outputs[fg->nb_outputs - 1]->name = describe_filter_link(fg, cur, 0); + ofilter->name = describe_filter_link(fg, cur, 0); cur = cur->next; - fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; + ofilter->out_tmp->next = NULL; } fail: diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 848b817e9c..bd1d451ff7 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -3258,10 +3258,12 @@ static int opt_audio_qscale(void *optctx, const char *opt, const char *arg) static int opt_filter_complex(void *optctx, const char *opt, const char *arg) { + FilterGraph *fg; ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); - filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; - filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg); - if (!filtergraphs[nb_filtergraphs - 1]->graph_desc) + fg = filtergraphs[nb_filtergraphs - 1]; + fg->index = nb_filtergraphs - 1; + fg->graph_desc = av_strdup(arg); + if (!fg->graph_desc) return AVERROR(ENOMEM); input_stream_potentially_available = 1; @@ -3271,13 +3273,15 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg) static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) { + FilterGraph *fg; uint8_t *graph_desc = read_file(arg); if (!graph_desc) return AVERROR(EINVAL); ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); - filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; - filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc; + fg = filtergraphs[nb_filtergraphs - 1]; + fg->index = nb_filtergraphs - 1; + fg->graph_desc = graph_desc; input_stream_potentially_available = 1; From 2e7ef008e312bde7c151034628adc2da04313566 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 14:34:47 +0100 Subject: [PATCH 376/894] fftools/cmdutils: Make allocate_array_elem() return ptr to new element Signed-off-by: Andreas Rheinhardt --- fftools/cmdutils.c | 6 ++++-- fftools/cmdutils.h | 4 ++-- fftools/ffmpeg_filter.c | 13 ++++--------- fftools/ffmpeg_opt.c | 9 +++------ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 1464b122df..0b57552e5c 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2216,8 +2216,9 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) { - void *new_elem, **array = (void**)ptr; + void *new_elem, **array; + memcpy(&array, ptr, sizeof(array)); if (*nb_elems == INT_MAX) { av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); exit_program(1); @@ -2226,8 +2227,9 @@ void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) if (!new_elem) exit_program(1); GROW_ARRAY(array, *nb_elems); + memcpy(ptr, &array, sizeof(array)); array[*nb_elems - 1] = new_elem; - return array; + return new_elem; } double get_rotation(int32_t *displaymatrix) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index ae78e60f4c..82cda208be 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -638,7 +638,7 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); * @param elem_size size of the new element to allocate * @param nb_elems pointer to the number of elements of the array array; * *nb_elems will be incremented by one by this function. - * @return reallocated array + * @return pointer to the newly allocated entry */ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); @@ -648,7 +648,7 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) #define ALLOC_ARRAY_ELEM(array, nb_elems)\ - array = allocate_array_elem(array, sizeof(*array[0]), &nb_elems) + allocate_array_elem(&array, sizeof(*array[0]), &nb_elems) #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 7263ea5f03..501a0acd61 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -166,16 +166,14 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) exit_program(1); fg->index = nb_filtergraphs; - ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); - ofilter = fg->outputs[0]; + ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); ofilter->ost = ost; ofilter->graph = fg; ofilter->format = -1; ost->filter = ofilter; - ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); - ifilter = fg->inputs[0]; + ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); ifilter->ist = ist; ifilter->graph = fg; ifilter->format = -1; @@ -281,8 +279,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->decoding_needed |= DECODING_FOR_FILTER; ist->st->discard = AVDISCARD_NONE; - ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); - ifilter = fg->inputs[fg->nb_inputs - 1]; + ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); ifilter->ist = ist; ifilter->graph = fg; ifilter->format = -1; @@ -318,9 +315,7 @@ int init_complex_filtergraph(FilterGraph *fg) init_input_filter(fg, cur); for (cur = outputs; cur;) { - OutputFilter *ofilter; - ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); - ofilter = fg->outputs[fg->nb_outputs - 1]; + OutputFilter *const ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); ofilter->graph = fg; ofilter->out_tmp = cur; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index bd1d451ff7..eea57a6974 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1265,8 +1265,7 @@ static int open_input_file(OptionsContext *o, const char *filename) /* dump the file content */ av_dump_format(ic, nb_input_files, filename, 0); - ALLOC_ARRAY_ELEM(input_files, nb_input_files); - f = input_files[nb_input_files - 1]; + f = ALLOC_ARRAY_ELEM(input_files, nb_input_files); f->ctx = ic; f->ist_index = nb_input_streams - ic->nb_streams; @@ -2260,8 +2259,7 @@ static int open_output_file(OptionsContext *o, const char *filename) } } - ALLOC_ARRAY_ELEM(output_files, nb_output_files); - of = output_files[nb_output_files - 1]; + of = ALLOC_ARRAY_ELEM(output_files, nb_output_files); of->ost_index = nb_output_streams; of->recording_time = o->recording_time; @@ -3278,8 +3276,7 @@ static int opt_filter_complex_script(void *optctx, const char *opt, const char * if (!graph_desc) return AVERROR(EINVAL); - ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); - fg = filtergraphs[nb_filtergraphs - 1]; + fg = ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); fg->index = nb_filtergraphs - 1; fg->graph_desc = graph_desc; From 2d0bfbd0fafe5e869919120758903801f91530fa Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 14:56:30 +0100 Subject: [PATCH 377/894] fftools/cmdutils: Use av_dynarray_add_nofree() Simplifies code and reduces the number of allocations a bit by overallocating. Signed-off-by: Andreas Rheinhardt --- fftools/cmdutils.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 0b57552e5c..3c8e5a82cd 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2216,19 +2216,13 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) { - void *new_elem, **array; + void *new_elem; - memcpy(&array, ptr, sizeof(array)); - if (*nb_elems == INT_MAX) { - av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); + if (!(new_elem = av_mallocz(elem_size)) || + av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) { + av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); exit_program(1); } - new_elem = av_mallocz(elem_size); - if (!new_elem) - exit_program(1); - GROW_ARRAY(array, *nb_elems); - memcpy(ptr, &array, sizeof(array)); - array[*nb_elems - 1] = new_elem; return new_elem; } From b886512ef2503fc585c302484be71475d3100480 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 20:30:33 +0100 Subject: [PATCH 378/894] fftools/ffmpeg: Avoid allocating+freeing frame, check allocations Fixes a potential crash upon av_frame_alloc() failure. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 11 ++++------- fftools/ffmpeg_opt.c | 4 ++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 47e6a8683e..b0b32a69f2 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1291,7 +1291,7 @@ static void do_video_out(OutputFile *of, int forced_keyframe = 0; double pts_time; - if (i < nb0_frames && ost->last_frame) { + if (i < nb0_frames && ost->last_frame->buf[0]) { in_picture = ost->last_frame; } else in_picture = next_picture; @@ -1419,13 +1419,10 @@ static void do_video_out(OutputFile *of, do_video_stats(ost, frame_size); } - if (!ost->last_frame) - ost->last_frame = av_frame_alloc(); av_frame_unref(ost->last_frame); - if (next_picture && ost->last_frame) - av_frame_ref(ost->last_frame, next_picture); - else - av_frame_free(&ost->last_frame); + if (next_picture) + if (av_frame_ref(ost->last_frame, next_picture) < 0) + goto error; return; error: diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index eea57a6974..a703798586 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1905,6 +1905,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ost->avfilter = get_ost_filters(o, oc, ost); if (!ost->avfilter) exit_program(1); + + ost->last_frame = av_frame_alloc(); + if (!ost->last_frame) + exit_program(1); } else { MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st); } From fc01a703dea4fe4f2eff73480958ee6c75aa8c30 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 20:39:04 +0100 Subject: [PATCH 379/894] fftools/ffmpeg: Avoid creating unnecessary reference The only caller of do_video_out() doesn't need the frame afterwards, ergo one can replace an av_frame_ref() by av_frame_move_ref(). Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b0b32a69f2..855db934bf 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1138,6 +1138,7 @@ static void do_subtitle_out(OutputFile *of, } } +/* May modify/reset next_picture */ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *next_picture) @@ -1421,8 +1422,7 @@ static void do_video_out(OutputFile *of, av_frame_unref(ost->last_frame); if (next_picture) - if (av_frame_ref(ost->last_frame, next_picture) < 0) - goto error; + av_frame_move_ref(ost->last_frame, next_picture); return; error: From 6c57e0b4a8825de01e363bc6a6ab598aaf4188e4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 21:19:04 +0100 Subject: [PATCH 380/894] avutil/frame: Treat frame as uninitialized in get_frame_defaults() Currently, it also tests whether extended_data points to something different than the AVFrame's data array and frees extended_data if it is different. Yet this is only necessary for one of its three callers, namely av_frame_unref(); meanwhile the other two callers took measures to avoid this (or rather, to make it to an av_free(NULL)). This commit moves this chunk to av_frame_unref() (so that get_frame_defaults() now treats its input as uninitialized) and removes the now superfluous code in the other two callers. Signed-off-by: Andreas Rheinhardt --- libavutil/frame.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index 64eed5b0dd..0912ad9131 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -52,9 +52,6 @@ const char *av_get_colorspace_name(enum AVColorSpace val) #endif static void get_frame_defaults(AVFrame *frame) { - if (frame->extended_data != frame->data) - av_freep(&frame->extended_data); - memset(frame, 0, sizeof(*frame)); frame->pts = @@ -99,12 +96,11 @@ static void wipe_side_data(AVFrame *frame) AVFrame *av_frame_alloc(void) { - AVFrame *frame = av_mallocz(sizeof(*frame)); + AVFrame *frame = av_malloc(sizeof(*frame)); if (!frame) return NULL; - frame->extended_data = NULL; get_frame_defaults(frame); return frame; @@ -457,6 +453,9 @@ void av_frame_unref(AVFrame *frame) av_buffer_unref(&frame->opaque_ref); av_buffer_unref(&frame->private_ref); + if (frame->extended_data != frame->data) + av_freep(&frame->extended_data); + get_frame_defaults(frame); } @@ -468,7 +467,6 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src) *dst = *src; if (src->extended_data == src->data) dst->extended_data = dst->data; - memset(src, 0, sizeof(*src)); get_frame_defaults(src); } From 847d1991388cec36b940964de40a289b3bf97976 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 23:18:35 +0100 Subject: [PATCH 381/894] avformat/takdec: Simplify data->hex conversion Signed-off-by: Andreas Rheinhardt --- libavformat/takdec.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 839e3cc781..6bb26683b4 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -109,7 +109,7 @@ static int tak_read_header(AVFormatContext *s) break; case TAK_METADATA_MD5: { uint8_t md5[16]; - int i; + char md5_hex[2 * sizeof(md5) + 1]; if (size != 19) return AVERROR_INVALIDDATA; @@ -121,10 +121,9 @@ static int tak_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - av_log(s, AV_LOG_VERBOSE, "MD5="); - for (i = 0; i < 16; i++) - av_log(s, AV_LOG_VERBOSE, "%02x", md5[i]); - av_log(s, AV_LOG_VERBOSE, "\n"); + ff_data_to_hex(md5_hex, md5, sizeof(md5), 1); + md5_hex[2 * sizeof(md5)] = '\0'; + av_log(s, AV_LOG_VERBOSE, "MD5=%s\n", md5_hex); break; } case TAK_METADATA_END: { From 228b25ad9bfef62338417fe607826dd33163ca69 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 3 Dec 2021 23:26:44 +0100 Subject: [PATCH 382/894] avformat/smoothstreamingenc: Move buffers to the end of structs This reduces codesize because the offsets of commonly used elements are now smaller and thus need less bytes to encode in ptr+offset addressing modes (with GCC 11.2 on x64: 0x1b8b -> 0x1a7b). Signed-off-by: Andreas Rheinhardt --- libavformat/smoothstreamingenc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 6bede7c254..a0ea5b8fa8 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -40,17 +40,15 @@ #include "libavutil/intreadwrite.h" typedef struct Fragment { - char file[1024]; - char infofile[1024]; int64_t start_time, duration; int n; int64_t start_pos, size; + char file[1024]; + char infofile[1024]; } Fragment; typedef struct OutputStream { AVFormatContext *ctx; - char dirname[1024]; - uint8_t iobuf[32768]; URLContext *out; // Current output stream where all output is written URLContext *out2; // Auxiliary output stream where all output is also written URLContext *tail_out; // The actual main output stream, if we're currently seeked back to write elsewhere @@ -64,6 +62,8 @@ typedef struct OutputStream { char *private_str; int packet_size; int audio_tag; + char dirname[1024]; + uint8_t iobuf[32768]; } OutputStream; typedef struct SmoothStreamingContext { From ef00d40e32e71cc18cc40ee2c90714b31d0a3ce5 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 6 Dec 2021 16:35:47 +0530 Subject: [PATCH 383/894] doc/filters: note duration range in xfade --- doc/filters.texi | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/filters.texi b/doc/filters.texi index 3edf3f50b0..8eff460cd9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -22989,6 +22989,7 @@ Default transition effect is fade. @item duration Set cross fade duration in seconds. +Range is 0 to 60 seconds. Default duration is 1 second. @item offset From b0b90100bfda8c5cf95889e00183589de0abce60 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 6 Dec 2021 12:20:21 +0100 Subject: [PATCH 384/894] avcodec/libopenh264dec: Increase array sizes, fix stack-buffer overread av_image_copy() expects an array of four pointers and linesizes according to its declaration; it currently only pointers that are actually in use (depending upon the pixel format), but this might change at any time. It has already happened for the linesizes in d7bc52bf456deba0f32d9fe5c288ec441f1ebef5 and so increasing their array fixes a stack-buffer overread. This fixes a -Wstringop-overflow= and -Wstringop-overread warning from GCC 11.2. Reviewed-by: Linjie Fu Signed-off-by: Andreas Rheinhardt --- libavcodec/libopenh264dec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c index ea70a8e143..7f5e85402a 100644 --- a/libavcodec/libopenh264dec.c +++ b/libavcodec/libopenh264dec.c @@ -91,8 +91,8 @@ static int svc_decode_frame(AVCodecContext *avctx, void *data, { SVCContext *s = avctx->priv_data; SBufferInfo info = { 0 }; - uint8_t* ptrs[3]; - int ret, linesize[3]; + uint8_t *ptrs[4] = { NULL }; + int ret, linesize[4]; AVFrame *avframe = data; DECODING_STATE state; #if OPENH264_VER_AT_LEAST(1, 7) @@ -140,6 +140,7 @@ static int svc_decode_frame(AVCodecContext *avctx, void *data, linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; + linesize[3] = 0; av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height); avframe->pts = info.uiOutYuvTimeStamp; From 59b4e7cbd87889c0bac710ac7f62782b637419a1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Dec 2021 20:11:35 +0100 Subject: [PATCH 385/894] avformat/mov: Check for EOF in mov_read_glbl() Fixes: Infinite loop Fixes: 41351/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-5433895854669824 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 5c74d099da..bf9e58197b 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1930,6 +1930,8 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) // wrap a whole fiel atom inside of a glbl atom. unsigned size = avio_rb32(pb); unsigned type = avio_rl32(pb); + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; avio_seek(pb, -8, SEEK_CUR); if (type == MKTAG('f','i','e','l') && size == atom.size) return mov_read_default(c, pb, atom); From 235ac7b4925ab963afd7719577a8fd6ce25b4d5f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Dec 2021 20:33:30 +0100 Subject: [PATCH 386/894] avcodec/avpacket: Perform fewer reallocations in repeated av_grow_packet() Fixes: Timeout Fixes: 41446/clusterfuzz-testcase-minimized-ffmpeg_dem_SAMI_fuzzer-4667644540747776 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/avpacket.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index d8d8fef3b9..a0134e405c 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -142,7 +142,14 @@ int av_grow_packet(AVPacket *pkt, int grow_by) if (new_size + data_offset > pkt->buf->size || !av_buffer_is_writable(pkt->buf)) { - int ret = av_buffer_realloc(&pkt->buf, new_size + data_offset); + int ret; + + // allocate slightly more than requested to avoid excessive + // reallocations + if (new_size + data_offset < INT_MAX - new_size/16) + new_size += new_size/16; + + ret = av_buffer_realloc(&pkt->buf, new_size + data_offset); if (ret < 0) { pkt->data = old_data; return ret; From cd95ac7e3301b13034f5503ae1bed9dbafee0689 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Dec 2021 21:07:36 +0100 Subject: [PATCH 387/894] tools/target_dec_fuzzer: adjust threshold for gem Fixes: Timeout Fixes: 42035/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_GEM_fuzzer-5033604191748096 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index e27c45ddaa..5b21d6715f 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -166,6 +166,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_FLAC: maxsamples /= 1024; break; case AV_CODEC_ID_FLV1: maxpixels /= 1024; break; case AV_CODEC_ID_G2M: maxpixels /= 1024; break; + case AV_CODEC_ID_GEM: maxpixels /= 512; break; case AV_CODEC_ID_GDV: maxpixels /= 512; break; case AV_CODEC_ID_GIF: maxpixels /= 16; break; case AV_CODEC_ID_H264: maxpixels /= 256; break; From e901716dafe4aba17c30b13403d350661d4d5fbf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 3 Dec 2021 18:06:34 +0100 Subject: [PATCH 388/894] tools/target_dec_fuzzer: Adjust threshold for HQ_HQA Fixes: Timeout Fixes: 41120/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HQ_HQA_fuzzer-6327761690558464 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 5b21d6715f..0c59242e3e 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -173,6 +173,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_HAP: maxpixels /= 128; break; case AV_CODEC_ID_HEVC: maxpixels /= 16384; break; case AV_CODEC_ID_HNM4_VIDEO: maxpixels /= 128; break; + case AV_CODEC_ID_HQ_HQA: maxpixels /= 128; break; case AV_CODEC_ID_IFF_ILBM: maxpixels /= 128; break; case AV_CODEC_ID_INDEO4: maxpixels /= 128; break; case AV_CODEC_ID_INTERPLAY_ACM: maxsamples /= 16384; break; From 51d5e90158971940ff18ec8b10934edd430c6eaa Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Dec 2021 21:11:48 +0100 Subject: [PATCH 389/894] avcodec/gemdec: Move all support checks before image allocation Reviewed-by: Peter Ross Signed-off-by: Michael Niedermayer --- libavcodec/gemdec.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c index eee21a50d4..fd14b22390 100644 --- a/libavcodec/gemdec.c +++ b/libavcodec/gemdec.c @@ -157,10 +157,22 @@ static int gem_decode_frame(AVCodecContext *avctx, if (header_size >= 11) tag = bytestream2_peek_be32(&gb); - if (tag == AV_RB32("STTT") || tag == AV_RB32("TIMG") || tag == AV_RB32("XIMG") || - planes == 1 || planes == 2 || planes == 3 || planes == 4 || - planes == 8 || planes == 16 || planes == 24) { - } else { + if (tag == AV_RB32("STTT")) { + if (planes != 4) { + avpriv_request_sample(avctx, "STTT planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + } else if (tag == AV_RB32("TIMG")) { + if (planes != 15) { + avpriv_request_sample(avctx, "TIMG planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + } else if (tag == AV_RB32("XIMG")) { + if (planes != 1 && planes != 2 && planes != 4 && planes != 8 && planes != 16 && planes != 24 && planes != 32) { + avpriv_request_sample(avctx, "XIMG planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + } else if (planes != 1 && planes != 2 && planes != 3 && planes != 4 && planes != 8 && planes != 16 && planes != 24) { avpriv_request_sample(avctx, "planes=%d", planes); return AVERROR_PATCHWELCOME; } @@ -184,14 +196,12 @@ static int gem_decode_frame(AVCodecContext *avctx, palette[i] = 0xFF000000 | r << 16 | g << 8 | b; } } else { - avpriv_request_sample(avctx, "STTT planes=%d", planes); - return AVERROR_PATCHWELCOME; + av_assert0(0); } } else if (tag == AV_RB32("TIMG")) { bytestream2_skip(&gb, 4); if (planes != 15) { - avpriv_request_sample(avctx, "TIMG planes=%d", planes); - return AVERROR_PATCHWELCOME; + av_assert0(0); } } else if (tag == AV_RB32("XIMG")) { bytestream2_skip(&gb, 6); @@ -215,8 +225,7 @@ static int gem_decode_frame(AVCodecContext *avctx, row_width = avctx->width * pixel_size; put_lines = put_lines_bytes; } else { - avpriv_request_sample(avctx, "XIMG planes=%d", planes); - return AVERROR_PATCHWELCOME; + av_assert0(0); } } else if (planes == 1) { palette[0] = 0xFFFFFFFF; @@ -244,7 +253,8 @@ static int gem_decode_frame(AVCodecContext *avctx, planes = 1; row_width = avctx->width * pixel_size; put_lines = put_lines_bytes; - } + } else + av_assert0(0); ret = av_reallocp_array(&avctx->priv_data, planes, row_width); if (ret < 0) From b5ba74053c1ef9f38d9e7b3a036675f06d2b2714 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 3 Dec 2021 17:42:22 +0100 Subject: [PATCH 390/894] avformat/mov: Disallow duplicate smdm Fixes: memleak Fixes: 39879/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-5327819907923968 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index bf9e58197b..ff5a55d0e6 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5407,6 +5407,9 @@ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version); return 0; } + if (sc->mastering) + return AVERROR_INVALIDDATA; + avio_skip(pb, 3); /* flags */ sc->mastering = av_mastering_display_metadata_alloc(); From 3f3772e4443c980b65e80859fdaaf3970f6c7fe4 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 3 Dec 2021 22:43:38 +0100 Subject: [PATCH 391/894] packet: add description for the AVPacket.time_base field This description documents the field. Thanks to elenril for suggesting the phrasing. --- libavcodec/packet.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/packet.h b/libavcodec/packet.h index 9baff24635..4a349fe051 100644 --- a/libavcodec/packet.h +++ b/libavcodec/packet.h @@ -410,6 +410,9 @@ typedef struct AVPacket { /** * Time base of the packet's timestamps. + * In the future, this field may be set on packets output by encoders or + * demuxers, but its value will be by default ignored on input to decoders + * or muxers. */ AVRational time_base; } AVPacket; From f3a8d208c0826b57ab250fd716e23c54be689254 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 1 Dec 2021 20:31:27 +0100 Subject: [PATCH 392/894] fftools/ffmpeg_opt: Improve checks for truncation/alloc error Do this by switching from the dynamic buffer API to the AVBPrint API; the former has no defined way to check for errors. This also avoids allocating an AVIOContext. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index a703798586..0dd18d2127 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -34,6 +34,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/avutil.h" +#include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/fifo.h" @@ -1645,29 +1646,26 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str) } /* read file contents into a string */ -static uint8_t *read_file(const char *filename) +static char *read_file(const char *filename) { AVIOContext *pb = NULL; - AVIOContext *dyn_buf = NULL; int ret = avio_open(&pb, filename, AVIO_FLAG_READ); - uint8_t buf[1024], *str; + AVBPrint bprint; + char *str; if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); return NULL; } - ret = avio_open_dyn_buf(&dyn_buf); + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX); + avio_closep(&pb); if (ret < 0) { - avio_closep(&pb); + av_bprint_finalize(&bprint, NULL); return NULL; } - while ((ret = avio_read(pb, buf, sizeof(buf))) > 0) - avio_write(dyn_buf, buf, ret); - avio_w8(dyn_buf, 0); - avio_closep(&pb); - - ret = avio_close_dyn_buf(dyn_buf, &str); + ret = av_bprint_finalize(&bprint, &str); if (ret < 0) return NULL; return str; @@ -3276,7 +3274,7 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg) static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) { FilterGraph *fg; - uint8_t *graph_desc = read_file(arg); + char *graph_desc = read_file(arg); if (!graph_desc) return AVERROR(EINVAL); From 6fc0fc5441e00b2cbc28f5e5f7e2a8f97c73f822 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 17:06:06 +0100 Subject: [PATCH 393/894] fftools/ffmpeg_opt: Improve alloc/truncation checks when reading lines Do this by switching from the dynamic buffer API to the AVBPrint API; the former has no defined way to check for errors. This also avoids allocating an AVIOContext. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 0dd18d2127..b5996a9273 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1352,23 +1352,18 @@ static int open_input_file(OptionsContext *o, const char *filename) return 0; } -static uint8_t *get_line(AVIOContext *s) +static char *get_line(AVIOContext *s, AVBPrint *bprint) { - AVIOContext *line; - uint8_t *buf; char c; - if (avio_open_dyn_buf(&line) < 0) { + while ((c = avio_r8(s)) && c != '\n') + av_bprint_chars(bprint, c, 1); + + if (!av_bprint_is_complete(bprint)) { av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n"); exit_program(1); } - - while ((c = avio_r8(s)) && c != '\n') - avio_w8(line, c); - avio_w8(line, 0); - avio_close_dyn_buf(line, &buf); - - return buf; + return bprint->str; } static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s) @@ -1499,20 +1494,21 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->autoscale = 1; MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) { + AVBPrint bprint; + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); do { - buf = get_line(s); - if (!buf[0] || buf[0] == '#') { - av_free(buf); + av_bprint_clear(&bprint); + buf = get_line(s, &bprint); + if (!buf[0] || buf[0] == '#') continue; - } if (!(arg = strchr(buf, '='))) { av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); exit_program(1); } *arg++ = 0; av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); - av_free(buf); } while (!s->eof_reached); + av_bprint_finalize(&bprint, NULL); avio_closep(&s); } if (ret) { From 007819a5bc0d3c01c0de26d9e1c6f909877e7c45 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 11:06:54 +0100 Subject: [PATCH 394/894] lavd/jack: increase buffer size for snprintf() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maximum output size with a 32-bit int is 17 bytes, or 26 with a 64-bit int. Silences the following gcc 10 warning: src/libavdevice/jack.c: In function ‘audio_read_header’: src/libavdevice/jack.c:171:45: warning: ‘snprintf’ output may be truncated before the last format character [-Wformat-truncation=] 171 | snprintf(str, sizeof(str), "input_%d", i + 1); | ^ src/libavdevice/jack.c:171:9: note: ‘snprintf’ output between 8 and 17 bytes into a destination of size 16 171 | snprintf(str, sizeof(str), "input_%d", i + 1); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- libavdevice/jack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/jack.c b/libavdevice/jack.c index 31534134f3..0d5465e407 100644 --- a/libavdevice/jack.c +++ b/libavdevice/jack.c @@ -167,7 +167,7 @@ static int start_jack(AVFormatContext *context) /* Register JACK ports */ for (i = 0; i < self->nports; i++) { - char str[16]; + char str[32]; snprintf(str, sizeof(str), "input_%d", i + 1); self->ports[i] = jack_port_register(self->client, str, JACK_DEFAULT_AUDIO_TYPE, From e1151fbf224da62f75fa975a1b18b7e74a13b1b1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 11:27:02 +0100 Subject: [PATCH 395/894] lavd/v4l2: do not clobber the context FD in v4l2_get_device_list() The FD opened here is local to the loop iteration, there is no reason to store it in the context. Since read_header() may have already been called, this may ovewrite an existing valid FD. --- libavdevice/v4l2.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index b5997fba33..4b7984f1b0 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -1033,16 +1033,17 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l return ret; } while ((entry = readdir(dir))) { + int fd = -1; char device_name[256]; if (!v4l2_is_v4l_dev(entry->d_name)) continue; snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); - if ((s->fd = device_open(ctx, device_name)) < 0) + if ((fd = device_open(ctx, device_name)) < 0) continue; - if (v4l2_ioctl(s->fd, VIDIOC_QUERYCAP, &cap) < 0) { + if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", av_err2str(ret)); goto fail; @@ -1064,8 +1065,7 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l &device_list->nb_devices, device)) < 0) goto fail; - v4l2_close(s->fd); - s->fd = -1; + v4l2_close(fd); continue; fail: @@ -1074,9 +1074,7 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l av_freep(&device->device_description); av_freep(&device); } - if (s->fd >= 0) - v4l2_close(s->fd); - s->fd = -1; + v4l2_close(fd); break; } closedir(dir); From b532ca3d2f1f1caab71c0aab979949882b695198 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 15:58:14 +0100 Subject: [PATCH 396/894] lavd/v4l2: reduce variable scope device and cap are local to the loop iteration, there is no need for them to retain their values. Especially for device it may be dangerous, since it points to av_malloc'ed data. --- libavdevice/v4l2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 4b7984f1b0..fefea54142 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -1019,8 +1019,6 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l struct video_data *s = ctx->priv_data; DIR *dir; struct dirent *entry; - AVDeviceInfo *device = NULL; - struct v4l2_capability cap; int ret = 0; if (!device_list) @@ -1033,6 +1031,8 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l return ret; } while ((entry = readdir(dir))) { + AVDeviceInfo *device = NULL; + struct v4l2_capability cap; int fd = -1; char device_name[256]; From 877b6a9e82f73e772b8ac40d4b119f21ee037f0f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 11:29:07 +0100 Subject: [PATCH 397/894] lavd/v4l2: detect device name truncation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Silences the following warning with gcc 10: src/libavdevice/v4l2.c: In function ‘v4l2_get_device_list’: src/libavdevice/v4l2.c:1042:64: warning: ‘%s’ directive output may be truncated writing up to 255 bytes into a region of size 251 [-Wformat-truncation=] 1042 | ret = snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); | ^~ src/libavdevice/v4l2.c:1042:15: note: ‘snprintf’ output between 6 and 261 bytes into a destination of size 256 1042 | ret = snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Previous patches intending to silence it have proposed increasing the buffer size, but doing that correctly seems to be tricky. Failing on truncation is simpler and just as effective (as excessively long device names are unlikely). --- libavdevice/v4l2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index fefea54142..2ecfb9fae7 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -1033,13 +1033,19 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l while ((entry = readdir(dir))) { AVDeviceInfo *device = NULL; struct v4l2_capability cap; - int fd = -1; + int fd = -1, size; char device_name[256]; if (!v4l2_is_v4l_dev(entry->d_name)) continue; - snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); + size = snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); + if (size >= sizeof(device_name)) { + av_log(ctx, AV_LOG_ERROR, "Device name too long.\n"); + ret = AVERROR(ENOSYS); + break; + } + if ((fd = device_open(ctx, device_name)) < 0) continue; From 177a328c7c7e3a2c10296abf20b0b40207153c76 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 11:52:55 +0100 Subject: [PATCH 398/894] lavfi/vf_subtitles: stop using deprecated ass_set_aspect_ratio() It has been deprecated in favor of ass_set_pixel_aspect() since version 0.11.0, roughly ~2014. Even Debian oldoldstable (stretch) has 0.13. --- configure | 2 +- libavfilter/vf_subtitles.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index a98a18abaa..04f319b197 100755 --- a/configure +++ b/configure @@ -6481,7 +6481,7 @@ enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "ar die "ERROR: libaribb24 requires version higher than 1.0.3 or --enable-gpl."; } enabled lv2 && require_pkg_config lv2 lilv-0 "lilv/lilv.h" lilv_world_new enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883 -enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init +enabled libass && require_pkg_config libass "libass >= 0.11.0" ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index 377160c72b..3fc4eeb63d 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -147,8 +147,8 @@ static int config_input(AVFilterLink *inlink) ass_set_frame_size (ass->renderer, inlink->w, inlink->h); if (ass->original_w && ass->original_h) - ass_set_aspect_ratio(ass->renderer, (double)inlink->w / inlink->h, - (double)ass->original_w / ass->original_h); + ass_set_pixel_aspect(ass->renderer, (double)inlink->w / inlink->h / + ((double)ass->original_w / ass->original_h)); if (ass->shaping != -1) ass_set_shaper(ass->renderer, ass->shaping); From 7e29e0278f228811f11e29b0692ada2f50fa7998 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 12:22:21 +0100 Subject: [PATCH 399/894] lavf/ftp: check for truncation in snprintf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Silences e.g. the following warning in gcc 10: src/libavformat/ftp.c: In function ‘ftp_move’: src/libavformat/ftp.c:1122:46: warning: ‘%s’ directive output may be truncated writing up to 4095 bytes into a region of size 4091 [-Wformat-truncation=] 1122 | snprintf(command, sizeof(command), "RNTO %s\r\n", path); | ^~ ~~~~ src/libavformat/ftp.c:1122:5: note: ‘snprintf’ output between 8 and 4103 bytes into a destination of size 4096 1122 | snprintf(command, sizeof(command), "RNTO %s\r\n", path); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- libavformat/ftp.c | 64 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/libavformat/ftp.c b/libavformat/ftp.c index 69caa7670c..883668b37b 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -250,13 +250,19 @@ static int ftp_auth(FTPContext *s) if (strpbrk(s->user, "\r\n")) return AVERROR(EINVAL); - snprintf(buf, sizeof(buf), "USER %s\r\n", s->user); + err = snprintf(buf, sizeof(buf), "USER %s\r\n", s->user); + if (err >= sizeof(buf)) + return AVERROR(ENOSYS); + err = ftp_send_command(s, buf, user_codes, NULL); if (err == 331) { if (s->password) { if (strpbrk(s->password, "\r\n")) return AVERROR(EINVAL); - snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password); + err = snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password); + if (err >= sizeof(buf)) + return AVERROR(ENOSYS); + err = ftp_send_command(s, buf, pass_codes, NULL); } else return AVERROR(EACCES); @@ -397,9 +403,13 @@ static int ftp_file_size(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; char *res = NULL; + int ret; static const int size_codes[] = {213, 0}; - snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); + if (ftp_send_command(s, command, size_codes, &res) == 213 && res && strlen(res) > 4) { s->filesize = strtoll(&res[4], NULL, 10); } else { @@ -416,9 +426,12 @@ static int ftp_retrieve(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; static const int retr_codes[] = {150, 125, 0}; - int resp_code; + int resp_code, ret; + + ret = snprintf(command, sizeof(command), "RETR %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); - snprintf(command, sizeof(command), "RETR %s\r\n", s->path); resp_code = ftp_send_command(s, command, retr_codes, NULL); if (resp_code != 125 && resp_code != 150) return AVERROR(EIO); @@ -432,9 +445,12 @@ static int ftp_store(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; static const int stor_codes[] = {150, 125, 0}; - int resp_code; + int resp_code, ret; + + ret = snprintf(command, sizeof(command), "STOR %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); - snprintf(command, sizeof(command), "STOR %s\r\n", s->path); resp_code = ftp_send_command(s, command, stor_codes, NULL); if (resp_code != 125 && resp_code != 150) return AVERROR(EIO); @@ -471,8 +487,12 @@ static int ftp_set_dir(FTPContext *s) { static const int cwd_codes[] = {250, 550, 0}; /* 550 is incorrect code */ char command[MAX_URL_SIZE]; + int ret; + + ret = snprintf(command, sizeof(command), "CWD %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); - snprintf(command, sizeof(command), "CWD %s\r\n", s->path); if (ftp_send_command(s, command, cwd_codes, NULL) != 250) return AVERROR(EIO); return 0; @@ -1082,13 +1102,23 @@ static int ftp_delete(URLContext *h) if ((ret = ftp_connect(h, h->filename)) < 0) goto cleanup; - snprintf(command, sizeof(command), "DELE %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "DELE %s\r\n", s->path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, del_codes, NULL) == 250) { ret = 0; goto cleanup; } - snprintf(command, sizeof(command), "RMD %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "RMD %s\r\n", s->path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, rmd_codes, NULL) == 250) ret = 0; else @@ -1110,7 +1140,12 @@ static int ftp_move(URLContext *h_src, URLContext *h_dst) if ((ret = ftp_connect(h_src, h_src->filename)) < 0) goto cleanup; - snprintf(command, sizeof(command), "RNFR %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "RNFR %s\r\n", s->path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, rnfr_codes, NULL) != 350) { ret = AVERROR(EIO); goto cleanup; @@ -1119,7 +1154,12 @@ static int ftp_move(URLContext *h_src, URLContext *h_dst) av_url_split(0, 0, 0, 0, 0, 0, 0, path, sizeof(path), h_dst->filename); - snprintf(command, sizeof(command), "RNTO %s\r\n", path); + ret = snprintf(command, sizeof(command), "RNTO %s\r\n", path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, rnto_codes, NULL) == 250) ret = 0; else From c0e46ad9a97628b7af78c21c4628f878ca658184 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 12:33:42 +0100 Subject: [PATCH 400/894] lavf/img2enc: avoid a useless copy of the url img2enc keeps a private (and possibly truncated) copy of the url that is never modified. Just use AVFormatContext.url instead. --- libavformat/img2enc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 62202de9f4..44895490e6 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -36,7 +36,6 @@ typedef struct VideoMuxData { const AVClass *class; /**< Class for private options. */ int img_number; int split_planes; /**< use independent file for each Y, U, V plane */ - char path[1024]; char tmp[4][1024]; char target[4][1024]; int update; @@ -53,14 +52,12 @@ static int write_header(AVFormatContext *s) AVStream *st = s->streams[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codecpar->format); - av_strlcpy(img->path, s->url, sizeof(img->path)); - if (st->codecpar->codec_id == AV_CODEC_ID_GIF) { img->muxer = "gif"; } else if (st->codecpar->codec_id == AV_CODEC_ID_FITS) { img->muxer = "fits"; } else if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { - const char *str = strrchr(img->path, '.'); + const char *str = strrchr(s->url, '.'); img->split_planes = str && !av_strcasecmp(str + 1, "y") && s->nb_streams == 1 @@ -136,29 +133,29 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) AVDictionary *options = NULL; if (img->update) { - av_strlcpy(filename, img->path, sizeof(filename)); + av_strlcpy(filename, s->url, sizeof(filename)); } else if (img->use_strftime) { time_t now0; struct tm *tm, tmpbuf; time(&now0); tm = localtime_r(&now0, &tmpbuf); - if (!strftime(filename, sizeof(filename), img->path, tm)) { + if (!strftime(filename, sizeof(filename), s->url, tm)) { av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } } else if (img->frame_pts) { - if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + if (av_get_frame_filename2(filename, sizeof(filename), s->url, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } else if (av_get_frame_filename2(filename, sizeof(filename), s->url, img->img_number, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s'. " "Use '-frames:v 1' for a single image, or '-update' option, or use a pattern such as %%03d within the filename.\n", - img->img_number, img->path); + img->img_number, s->url); return AVERROR(EINVAL); } for (i = 0; i < 4; i++) { From 6ebaccf327ce0fd88555fdd8b3f3deb019f0dc98 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 Nov 2021 15:40:16 +0100 Subject: [PATCH 401/894] lavf/protocols: avoid discarding const in avio_enum_protocols() Instead of storing the protocol pointer in the opaque iteration state, store just the index of the next protocol, similarly to how ff_urlcontext_child_class_iterate() works. --- libavformat/protocols.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavformat/protocols.c b/libavformat/protocols.c index b108aa6c7e..948fae411f 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -93,17 +93,17 @@ const AVClass *ff_urlcontext_child_class_iterate(void **iter) const char *avio_enum_protocols(void **opaque, int output) { - const URLProtocol **p = *opaque; + uintptr_t i; - p = p ? p + 1 : url_protocols; - *opaque = p; - if (!*p) { - *opaque = NULL; - return NULL; + for (i = (uintptr_t)*opaque; url_protocols[i]; i++) { + const URLProtocol *p = url_protocols[i]; + if ((output && p->url_write) || (!output && p->url_read)) { + *opaque = (void*)(uintptr_t)(i + 1); + return p->name; + } } - if ((output && (*p)->url_write) || (!output && (*p)->url_read)) - return (*p)->name; - return avio_enum_protocols(opaque, output); + *opaque = NULL; + return NULL; } const AVClass *avio_protocol_get_class(const char *name) From bb6f591c4938b98b748e43625a54015486a6ed94 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 Nov 2021 12:06:02 +0100 Subject: [PATCH 402/894] ffmpeg: drop useless framerate assignments If the input stream framerate is known, it will be configured on the relevant filtergraph input and get propagated to the output stream in the above line. That makes these assignments redundant. --- fftools/ffmpeg.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 855db934bf..6827899b90 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3293,10 +3293,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (!ost->frame_rate.num) ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); - if (ist && !ost->frame_rate.num) - ost->frame_rate = ist->framerate; - if (ist && !ost->frame_rate.num) - ost->frame_rate = ist->st->r_frame_rate; if (ist && !ost->frame_rate.num && !ost->max_frame_rate.num) { ost->frame_rate = (AVRational){25, 1}; av_log(NULL, AV_LOG_WARNING, From 011114f3e1593a2397871632937a2c23a1402efe Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 14:53:58 +0100 Subject: [PATCH 403/894] ffmpeg: change vsync value to an enum Stop explicitly defining VSCFR and DROP values, which were never documented. --- fftools/ffmpeg.c | 3 ++- fftools/ffmpeg.h | 16 +++++++++------- fftools/ffmpeg_opt.c | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 6827899b90..1c3c1d3dbf 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1143,7 +1143,8 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *next_picture) { - int ret, format_video_sync; + int ret; + enum VideoSyncMethod format_video_sync; AVPacket *pkt = ost->pkt; AVCodecContext *enc = ost->enc_ctx; AVRational frame_rate; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index cc7ba9bdca..83e37cbed7 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -47,12 +47,14 @@ #include "libswresample/swresample.h" -#define VSYNC_AUTO -1 -#define VSYNC_PASSTHROUGH 0 -#define VSYNC_CFR 1 -#define VSYNC_VFR 2 -#define VSYNC_VSCFR 0xfe -#define VSYNC_DROP 0xff +enum VideoSyncMethod { + VSYNC_AUTO = -1, + VSYNC_PASSTHROUGH, + VSYNC_CFR, + VSYNC_VFR, + VSYNC_VSCFR, + VSYNC_DROP, +}; #define MAX_STREAMS 1024 /* arbitrary sanity check value */ @@ -605,7 +607,7 @@ extern float dts_error_threshold; extern int audio_volume; extern int audio_sync_method; -extern int video_sync_method; +extern enum VideoSyncMethod video_sync_method; extern float frame_drop_threshold; extern int do_benchmark; extern int do_benchmark_all; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index b5996a9273..d478008866 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -147,7 +147,7 @@ float dts_error_threshold = 3600*30; int audio_volume = 256; int audio_sync_method = 0; -int video_sync_method = VSYNC_AUTO; +enum VideoSyncMethod video_sync_method = VSYNC_AUTO; float frame_drop_threshold = 0; int do_benchmark = 0; int do_benchmark_all = 0; From e3833e8a24b8498745b4b985a4df188b8d16b65a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 14:57:52 +0100 Subject: [PATCH 404/894] FATE: stop using numeric arguments to -vsync Symbolic names are always preferable. --- tests/fate/h264.mak | 4 ++-- tests/fate/hevc.mak | 2 +- tests/fate/mov.mak | 4 ++-- tests/fate/mpeg4.mak | 2 +- tests/fate/vcodec.mak | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index e034e6ae0f..e075b6f67f 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -342,7 +342,7 @@ fate-h264-conformance-frext-freh7_b: CMD = framecrc -i $(TARGET_SAM fate-h264-conformance-frext-frext01_jvc_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FREXT01_JVC_D.264 fate-h264-conformance-frext-frext02_jvc_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FREXT02_JVC_C.264 fate-h264-conformance-frext-frext1_panasonic_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt1_Panasonic.avc -fate-h264-conformance-frext-frext2_panasonic_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt2_Panasonic.avc -vsync 0 +fate-h264-conformance-frext-frext2_panasonic_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt2_Panasonic.avc -vsync passthrough fate-h264-conformance-frext-frext3_panasonic_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt3_Panasonic.avc fate-h264-conformance-frext-frext4_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt4_Panasonic.avc fate-h264-conformance-frext-frext_mmco4_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt_MMCO4_Sony_B.264 @@ -361,7 +361,7 @@ fate-h264-conformance-frext-hpcadq_brcm_b: CMD = framecrc -i $(TARGET_SAM fate-h264-conformance-frext-hpcafl_bcrm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAFL_BRCM_C.264 fate-h264-conformance-frext-hpcaflnl_bcrm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAFLNL_BRCM_C.264 fate-h264-conformance-frext-hpcalq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCALQ_BRCM_B.264 -fate-h264-conformance-frext-hpcamapalq_bcrm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMAPALQ_BRCM_B.264 -vsync 0 +fate-h264-conformance-frext-hpcamapalq_bcrm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMAPALQ_BRCM_B.264 -vsync passthrough fate-h264-conformance-frext-hpcamolq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMOLQ_BRCM_B.264 fate-h264-conformance-frext-hpcanl_brcm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCANL_BRCM_C.264 fate-h264-conformance-frext-hpcaq2lq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAQ2LQ_BRCM_B.264 diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 2a88eb4690..abe4264662 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -239,7 +239,7 @@ $(foreach N,$(HEVC_SAMPLES_444_8BIT),$(eval $(call FATE_HEVC_TEST_444_8BIT,$(N)) $(foreach N,$(HEVC_SAMPLES_444_12BIT),$(eval $(call FATE_HEVC_TEST_444_12BIT,$(N)))) $(foreach N,$(HEVC_SAMPLES_444_12BIT_LARGE),$(eval $(call FATE_HEVC_TEST_444_12BIT_LARGE,$(N)))) -fate-hevc-paramchange-yuv420p-yuv420p10: CMD = framecrc -vsync 0 -i $(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc -sws_flags area+accurate_rnd+bitexact +fate-hevc-paramchange-yuv420p-yuv420p10: CMD = framecrc -vsync passthrough -i $(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc -sws_flags area+accurate_rnd+bitexact FATE_HEVC_LARGE += fate-hevc-paramchange-yuv420p-yuv420p10 tests/data/hevc-mp4.mov: TAG = GEN diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 5ca992e181..e956380909 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -94,8 +94,8 @@ fate-mov-neg-firstpts-discard: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entri # with negative timestamps (skip_samples is not set for Vorbis, so ffmpeg computes start_time as negative if not specified by demuxer). fate-mov-neg-firstpts-discard-vorbis: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=start_time -bitexact $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard_vorbis.mp4 -# Makes sure that expected frames are generated for mov_neg_first_pts_discard.mov with -vsync 1 -fate-mov-neg-firstpts-discard-frames: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov -vsync 1 +# Makes sure that expected frames are generated for mov_neg_first_pts_discard.mov with -vsync cfr +fate-mov-neg-firstpts-discard-frames: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov -vsync cfr # Makes sure that no frame is dropped/duplicated with fps filter due to start_time / duration miscalculations. fate-mov-stream-shorter-than-movie: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_stream_shorter_than_movie.mov -vf fps=fps=24 -an diff --git a/tests/fate/mpeg4.mak b/tests/fate/mpeg4.mak index ed6a2fac20..26007f82f0 100644 --- a/tests/fate/mpeg4.mak +++ b/tests/fate/mpeg4.mak @@ -8,7 +8,7 @@ FATE_MPEG4-$(call DEMDEC, H263, H263) := $(addprefix fate-mpeg4-resolution-chang fate-mpeg4-bsf-unpack-bframes: CMD = md5 -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -c:v copy -bsf mpeg4_unpack_bframes -f avi FATE_MPEG4-$(call ALLYES, AVI_DEMUXER MPEG4_UNPACK_BFRAMES_BSF AVI_MUXER) += fate-mpeg4-bsf-unpack-bframes -fate-mpeg4-packed: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -vsync 1 +fate-mpeg4-packed: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -vsync cfr FATE_MPEG4-$(call ALLYES, AVI_DEMUXER MPEG4_DECODER) += fate-mpeg4-packed FATE_MPEG4-$(call DEMDEC, M4V, MPEG4) += fate-m4v fate-m4v-cfr diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index ef892366eb..2e6d16f1e7 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -4,8 +4,8 @@ fate-vsynth_lena-%: SRC = tests/data/vsynth_lena.yuv fate-vsynth3-%: SRC = tests/data/vsynth3.yuv fate-vsynth%: CODEC = $(word 3, $(subst -, ,$(@))) fate-vsynth%: FMT = avi -fate-vsynth%: CMD = enc_dec "rawvideo -s 352x288 -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s 352x288 -pix_fmt yuv420p -vsync 0 $(DECOPTS)" "$(KEEP_OVERRIDE)" "$(DECINOPTS)" -fate-vsynth3-%: CMD = enc_dec "rawvideo -s $(FATEW)x$(FATEH) -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s $(FATEW)x$(FATEH) -pix_fmt yuv420p -vsync 0 $(DECOPTS)" "" "$(DECINOPTS)" +fate-vsynth%: CMD = enc_dec "rawvideo -s 352x288 -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s 352x288 -pix_fmt yuv420p -vsync passthrough $(DECOPTS)" "$(KEEP_OVERRIDE)" "$(DECINOPTS)" +fate-vsynth3-%: CMD = enc_dec "rawvideo -s $(FATEW)x$(FATEH) -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s $(FATEW)x$(FATEH) -pix_fmt yuv420p -vsync passthrough $(DECOPTS)" "" "$(DECINOPTS)" fate-vsynth%: CMP_UNIT = 1 fate-vsynth%: REF = $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%=%) From 6ce954642878d792ee1f628e0f871763f07efe72 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 15:03:07 +0100 Subject: [PATCH 405/894] ffmpeg: deprecate passing numbers to -vsync There is never a reason to do this, using symbolic names is always preferred. --- doc/ffmpeg.texi | 16 +++++++++------- fftools/ffmpeg_opt.c | 7 +++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 20a547381c..164419cad3 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1620,23 +1620,25 @@ It is useful for when flow speed of output packets is important, such as live st Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. @item -vsync @var{parameter} Video sync method. -For compatibility reasons old values can be specified as numbers. -Newly added values will have to be specified as strings always. + +For compatibility reasons some of the values can be specified as numbers (shown +in parentheses in the following table). This is deprecated and will stop working +in the future. @table @option -@item 0, passthrough +@item passthrough (0) Each frame is passed with its timestamp from the demuxer to the muxer. -@item 1, cfr +@item cfr (1) Frames will be duplicated and dropped to achieve exactly the requested constant frame rate. -@item 2, vfr +@item vfr (2) Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp. @item drop As passthrough but destroys all timestamps, making the muxer generate fresh timestamps based on frame-rate. -@item -1, auto -Chooses between 1 and 2 depending on muxer capabilities. This is the +@item auto (-1) +Chooses between cfr and vfr depending on muxer capabilities. This is the default method. @end table diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index d478008866..42a65830a2 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1731,7 +1731,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in if ((frame_rate || max_frame_rate) && video_sync_method == VSYNC_PASSTHROUGH) - av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r/-fpsmax can produce invalid output files\n"); + av_log(NULL, AV_LOG_ERROR, "Using -vsync passthrough and -r/-fpsmax can produce invalid output files\n"); MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); if (frame_aspect_ratio) { @@ -3191,8 +3191,11 @@ static int opt_vsync(void *optctx, const char *opt, const char *arg) else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; else if (!av_strcasecmp(arg, "drop")) video_sync_method = VSYNC_DROP; - if (video_sync_method == VSYNC_AUTO) + if (video_sync_method == VSYNC_AUTO) { video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); + av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated," + " use a string argument as described in the manual.\n"); + } return 0; } From 9145c6d3b2e6e051b7450bcb96bdb3267271936c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 15:16:54 +0100 Subject: [PATCH 406/894] ffmpeg: move setting video sync method to new_video_stream() do_video_out() is the wrong place for it, since the necessary information is already known when creating the stream and its value should never change. --- fftools/ffmpeg.c | 25 +++---------------------- fftools/ffmpeg.h | 1 + fftools/ffmpeg_opt.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1c3c1d3dbf..1a415d396b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1144,7 +1144,6 @@ static void do_video_out(OutputFile *of, AVFrame *next_picture) { int ret; - enum VideoSyncMethod format_video_sync; AVPacket *pkt = ost->pkt; AVCodecContext *enc = ost->enc_ctx; AVRational frame_rate; @@ -1191,28 +1190,10 @@ static void do_video_out(OutputFile *of, nb0_frames = 0; // tracks the number of times the PREVIOUS frame should be duplicated, mostly for variable framerate (VFR) nb_frames = 1; - format_video_sync = video_sync_method; - if (format_video_sync == VSYNC_AUTO) { - if(!strcmp(of->ctx->oformat->name, "avi")) { - format_video_sync = VSYNC_VFR; - } else - format_video_sync = (of->ctx->oformat->flags & AVFMT_VARIABLE_FPS) ? ((of->ctx->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; - if ( ist - && format_video_sync == VSYNC_CFR - && input_files[ist->file_index]->ctx->nb_streams == 1 - && input_files[ist->file_index]->input_ts_offset == 0) { - format_video_sync = VSYNC_VSCFR; - } - if (format_video_sync == VSYNC_CFR && copy_ts) { - format_video_sync = VSYNC_VSCFR; - } - } - ost->is_cfr = (format_video_sync == VSYNC_CFR || format_video_sync == VSYNC_VSCFR); - if (delta0 < 0 && delta > 0 && - format_video_sync != VSYNC_PASSTHROUGH && - format_video_sync != VSYNC_DROP) { + ost->vsync_method != VSYNC_PASSTHROUGH && + ost->vsync_method != VSYNC_DROP) { if (delta0 < -0.6) { av_log(NULL, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); } else @@ -1222,7 +1203,7 @@ static void do_video_out(OutputFile *of, delta0 = 0; } - switch (format_video_sync) { + switch (ost->vsync_method) { case VSYNC_VSCFR: if (ost->frame_number == 0 && delta0 >= 0.5) { av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 83e37cbed7..9b200b806a 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -485,6 +485,7 @@ typedef struct OutputStream { /* video only */ AVRational frame_rate; AVRational max_frame_rate; + enum VideoSyncMethod vsync_method; int is_cfr; int force_fps; int top_field_first; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 42a65830a2..9c820ab73f 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1895,6 +1895,30 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ost->top_field_first = -1; MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); + ost->vsync_method = video_sync_method; + if (ost->vsync_method == VSYNC_AUTO) { + if (!strcmp(oc->oformat->name, "avi")) { + ost->vsync_method = VSYNC_VFR; + } else { + ost->vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ? + ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ? + VSYNC_PASSTHROUGH : VSYNC_VFR) : + VSYNC_CFR; + } + + if (ost->source_index >= 0 && ost->vsync_method == VSYNC_CFR) { + const InputStream *ist = input_streams[ost->source_index]; + const InputFile *ifile = input_files[ist->file_index]; + + if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0) + ost->vsync_method = VSYNC_VSCFR; + } + + if (ost->vsync_method == VSYNC_CFR && copy_ts) { + ost->vsync_method = VSYNC_VSCFR; + } + } + ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); ost->avfilter = get_ost_filters(o, oc, ost); if (!ost->avfilter) From 9f717ca92f77d94e9ac3e5676e5622c6ba847dc4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 18:38:54 +0100 Subject: [PATCH 407/894] ffmpeg: handle errors in print_sdp() Do not continue as if nothing happened. --- fftools/ffmpeg.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1a415d396b..0f1834cdbe 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2761,17 +2761,17 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return !eof_reached; } -static void print_sdp(void) +static int print_sdp(void) { char sdp[16384]; int i; - int j; + int j, ret; AVIOContext *sdp_pb; AVFormatContext **avc; for (i = 0; i < nb_output_files; i++) { if (!output_files[i]->header_written) - return; + return 0; } avc = av_malloc_array(nb_output_files, sizeof(*avc)); @@ -2784,26 +2784,34 @@ static void print_sdp(void) } } - if (!j) + if (!j) { + av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); + ret = AVERROR(EINVAL); goto fail; + } - av_sdp_create(avc, j, sdp, sizeof(sdp)); + ret = av_sdp_create(avc, j, sdp, sizeof(sdp)); + if (ret < 0) + goto fail; if (!sdp_filename) { printf("SDP:\n%s\n", sdp); fflush(stdout); } else { - if (avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL) < 0) { + ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL); + if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename); - } else { - avio_print(sdp_pb, sdp); - avio_closep(&sdp_pb); - av_freep(&sdp_filename); + goto fail; } + + avio_print(sdp_pb, sdp); + avio_closep(&sdp_pb); + av_freep(&sdp_filename); } fail: av_freep(&avc); + return ret; } static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) @@ -2959,8 +2967,13 @@ static int check_init_output_file(OutputFile *of, int file_index) av_dump_format(of->ctx, file_index, of->ctx->url, 1); nb_output_dumped++; - if (sdp_filename || want_sdp) - print_sdp(); + if (sdp_filename || want_sdp) { + ret = print_sdp(); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n"); + return ret; + } + } /* flush the muxing queues */ for (i = 0; i < of->ctx->nb_streams; i++) { From a454dfacd560e40fa5fea796f0d5b437f78e54e4 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Tue, 7 Dec 2021 17:26:05 +0530 Subject: [PATCH 408/894] avformat/concatf: ignore trailing whitespaces The concatf protocol returns an opaque error on open if concatf list file contains trailing newlines. Signed-off-by: Gyan Doshi Reviewed-by: James Almer --- libavformat/concat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/concat.c b/libavformat/concat.c index 2560811ff9..faeba2293a 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -245,6 +245,10 @@ static av_cold int concatf_open(URLContext *h, const char *uri, int flags) char *node_uri; int64_t size; size_t len = i; + int leading_spaces = strspn(cursor, " \n\t\r"); + + if (!cursor[leading_spaces]) + break; node_uri = av_get_token(&cursor, "\r\n"); if (!node_uri) { From 130e4c6f4c3a7daeaeee4d195c1122f21fbc95c7 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sun, 5 Dec 2021 21:12:28 +0800 Subject: [PATCH 409/894] avformat/rtsp: remove redundant assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/rtsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index deaed34db4..47120fdf61 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1178,8 +1178,8 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, char buf[MAX_URL_SIZE], buf1[MAX_URL_SIZE], *q; unsigned char ch; const char *p; - int ret, content_length, line_count = 0, request = 0; - unsigned char *content = NULL; + int ret, content_length, line_count, request; + unsigned char *content; start: line_count = 0; From f210766a55ea2db85b01038e0f4a4b8891d1903b Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sun, 5 Dec 2021 21:13:51 +0800 Subject: [PATCH 410/894] avformat/rtsp: free the alloc memory if failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/rtsp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 47120fdf61..5cffe0b6b5 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1245,8 +1245,10 @@ start: content = av_malloc(content_length + 1); if (!content) return AVERROR(ENOMEM); - if (ffurl_read_complete(rt->rtsp_hd, content, content_length) != content_length) + if (ffurl_read_complete(rt->rtsp_hd, content, content_length) != content_length) { + av_freep(&content); return AVERROR(EIO); + } content[content_length] = '\0'; } if (content_ptr) From 6d42af02f566c2a14a72bc13517add071c1d2a2b Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Mon, 6 Dec 2021 10:37:08 +0800 Subject: [PATCH 411/894] avformat/rtsp: add error code handling for ff_rtsp_skip_packet() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/rtsp.c | 15 ++++++++++----- libavformat/rtsp.h | 4 +++- libavformat/rtspenc.c | 7 +++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 5cffe0b6b5..bf25429187 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1145,7 +1145,7 @@ void ff_rtsp_parse_line(AVFormatContext *s, } /* skip a RTP/TCP interleaved packet */ -void ff_rtsp_skip_packet(AVFormatContext *s) +int ff_rtsp_skip_packet(AVFormatContext *s) { RTSPState *rt = s->priv_data; int ret, len, len1; @@ -1153,7 +1153,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) - return; + return ret < 0 ? ret : AVERROR(EIO); len = AV_RB16(buf + 1); av_log(s, AV_LOG_TRACE, "skipping RTP packet len=%d\n", len); @@ -1165,9 +1165,11 @@ void ff_rtsp_skip_packet(AVFormatContext *s) len1 = sizeof(buf); ret = ffurl_read_complete(rt->rtsp_hd, buf, len1); if (ret != len1) - return; + return ret < 0 ? ret : AVERROR(EIO); len -= len1; } + + return 0; } int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, @@ -1201,8 +1203,11 @@ start: if (ch == '$' && q == buf) { if (return_on_interleaved_data) { return 1; - } else - ff_rtsp_skip_packet(s); + } else { + ret = ff_rtsp_skip_packet(s); + if (ret < 0) + return ret; + } } else if (ch != '\r') { if ((q - buf) < sizeof(buf) - 1) *q++ = ch; diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index d6fdfe069c..8b64e29d70 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -560,8 +560,10 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, /** * Skip a RTP/TCP interleaved packet. + * + * @return 0 on success, < 0 on failure. */ -void ff_rtsp_skip_packet(AVFormatContext *s); +int ff_rtsp_skip_packet(AVFormatContext *s); /** * Connect to the RTSP server and set up the individual media streams. diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index e0fed1eebe..2a00b3e18d 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -200,8 +200,11 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL); if (ret < 0) return AVERROR(EPIPE); - if (ret == 1) - ff_rtsp_skip_packet(s); + if (ret == 1) { + ret = ff_rtsp_skip_packet(s); + if (ret < 0) + return ret; + } /* XXX: parse message */ if (rt->state != RTSP_STATE_STREAMING) return AVERROR(EPIPE); From f1c8c2583277767930da7d7cb6d79b582768c8e6 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 7 Dec 2021 20:46:34 +0800 Subject: [PATCH 412/894] avformat/rtsp: fix the error code from ffurl_read_complete() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavformat/rtsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index bf25429187..1e091c7380 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1197,7 +1197,7 @@ start: ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1); av_log(s, AV_LOG_TRACE, "ret=%d c=%02x [%c]\n", ret, ch, ch); if (ret != 1) - return AVERROR_EOF; + return ret < 0 ? ret : AVERROR(EIO); if (ch == '\n') break; if (ch == '$' && q == buf) { @@ -1250,9 +1250,9 @@ start: content = av_malloc(content_length + 1); if (!content) return AVERROR(ENOMEM); - if (ffurl_read_complete(rt->rtsp_hd, content, content_length) != content_length) { + if ((ret = ffurl_read_complete(rt->rtsp_hd, content, content_length)) != content_length) { av_freep(&content); - return AVERROR(EIO); + return ret < 0 ? ret : AVERROR(EIO); } content[content_length] = '\0'; } From b09ea67b40e342f5e4183e9ebc0c14801ecd218c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 6 Dec 2021 12:19:46 +0100 Subject: [PATCH 413/894] avcodec/libkvazaar: Increase array size av_image_copy() expects an array of four pointers according to its declaration; although it currently only touches pointers that are actually in use (depending upon the pixel format) this might change at any time (as has already happened for the linesizes in d7bc52bf456deba0f32d9fe5c288ec441f1ebef5). This fixes a -Wstringop-overflow= warning with GCC 11.2. Signed-off-by: Andreas Rheinhardt --- libavcodec/libkvazaar.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index aabe446a28..5f9ab43093 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -208,13 +208,19 @@ static int libkvazaar_encode(AVCodecContext *avctx, // Copy pixels from frame to input_pic. { + uint8_t *dst[4] = { + input_pic->data[0], + input_pic->data[1], + input_pic->data[2], + NULL, + }; int dst_linesizes[4] = { frame->width, frame->width / 2, frame->width / 2, 0 }; - av_image_copy(input_pic->data, dst_linesizes, + av_image_copy(dst, dst_linesizes, (const uint8_t **)frame->data, frame->linesize, frame->format, frame->width, frame->height); } From e38eaf47491a864b2180d1ade87ed0ef39dd6d34 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 18:52:29 +0100 Subject: [PATCH 414/894] avformat/utils: Make ff_data_to_hex() zero-terminate the string Most callers want it that way anyway. Signed-off-by: Andreas Rheinhardt --- libavformat/hls.c | 2 -- libavformat/hlsenc.c | 1 - libavformat/httpauth.c | 5 ----- libavformat/internal.h | 11 +++++++++++ libavformat/movenc.c | 1 - libavformat/omadec.c | 1 - libavformat/rtmpproto.c | 2 -- libavformat/sdp.c | 3 --- libavformat/takdec.c | 1 - libavformat/utils.c | 1 + 10 files changed, 12 insertions(+), 16 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 52a031ed54..557faf8e8d 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1284,7 +1284,6 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg, char iv[33], key[33], url[MAX_URL_SIZE]; ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); ff_data_to_hex(key, pls->key, sizeof(pls->key), 0); - iv[32] = key[32] = '\0'; if (strstr(seg->url, "://")) snprintf(url, sizeof(url), "crypto+%s", seg->url); else @@ -2074,7 +2073,6 @@ static int hls_read_header(AVFormatContext *s) if (strstr(in_fmt->name, "mov")) { char key[33]; ff_data_to_hex(key, pls->key, sizeof(pls->key), 0); - key[32] = '\0'; av_dict_set(&options, "decryption_key", key, AV_OPT_FLAG_DECODING_PARAM); } else if (!c->crypto_ctx.aes_ctx) { c->crypto_ctx.aes_ctx = av_aes_alloc(); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index cfd0c036d1..1c2a556375 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -745,7 +745,6 @@ static int do_encrypt(AVFormatContext *s, VariantStream *vs) memcpy(iv, hls->iv, sizeof(iv)); } ff_data_to_hex(buf, iv, sizeof(iv), 0); - buf[32] = '\0'; memcpy(hls->iv_string, buf, sizeof(hls->iv_string)); } diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index 4f79c78edc..0a98ff80a5 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -156,7 +156,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, for (i = 0; i < 2; i++) cnonce_buf[i] = av_get_random_seed(); ff_data_to_hex(cnonce, (const uint8_t*) cnonce_buf, sizeof(cnonce_buf), 1); - cnonce[2*sizeof(cnonce_buf)] = 0; md5ctx = av_md5_alloc(); if (!md5ctx) @@ -166,7 +165,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, username, ":", state->realm, ":", password, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); - A1hash[32] = 0; if (!strcmp(digest->algorithm, "") || !strcmp(digest->algorithm, "MD5")) { } else if (!strcmp(digest->algorithm, "MD5-sess")) { @@ -174,7 +172,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, A1hash, ":", digest->nonce, ":", cnonce, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); - A1hash[32] = 0; } else { /* Unsupported algorithm */ av_free(md5ctx); @@ -185,7 +182,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, method, ":", uri, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A2hash, hash, 16, 1); - A2hash[32] = 0; av_md5_init(md5ctx); update_md5_strings(md5ctx, A1hash, ":", digest->nonce, NULL); @@ -195,7 +191,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, ":", A2hash, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(response, hash, 16, 1); - response[32] = 0; av_free(md5ctx); diff --git a/libavformat/internal.h b/libavformat/internal.h index 20e93d9267..f43e408548 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -484,6 +484,17 @@ void ff_flush_packet_queue(AVFormatContext *s); */ int ff_mkdir_p(const char *path); +/** + * Write hexadecimal string corresponding to given binary data. The string + * is zero-terminated. + * + * @param buf the output string is written here; + * needs to be at least 2 * size + 1 bytes long. + * @param src the input data to be transformed. + * @param size the size (in byte) of src. + * @param lowercase determines whether to use the range [0-9a-f] or [0-9A-F]. + * @return buf. + */ char *ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase); /** diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 38ff90833a..0f912dd012 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4290,7 +4290,6 @@ static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *va char buf[150]; len = FFMIN(sizeof(buf) / 2 - 1, len); ff_data_to_hex(buf, value, len, 0); - buf[2 * len] = '\0'; avio_printf(pb, "\n", name, buf); } diff --git a/libavformat/omadec.c b/libavformat/omadec.c index a727cc4d66..4c418a5ff2 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -108,7 +108,6 @@ static void hex_log(AVFormatContext *s, int level, if (av_log_get_level() < level) return; ff_data_to_hex(buf, value, len, 1); - buf[len << 1] = '\0'; av_log(s, level, "%s: %s\n", name, buf); } diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index b14d23b919..34020bc383 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -1663,7 +1663,6 @@ static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce) av_md5_update(md5, rt->password, strlen(rt->password)); av_md5_final(md5, hash); ff_data_to_hex(hashstr1, hash, 16, 1); - hashstr1[32] = '\0'; av_md5_init(md5); av_md5_update(md5, method, strlen(method)); @@ -1673,7 +1672,6 @@ static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce) av_md5_update(md5, "/_definst_", strlen("/_definst_")); av_md5_final(md5, hash); ff_data_to_hex(hashstr2, hash, 16, 1); - hashstr2[32] = '\0'; av_md5_init(md5); av_md5_update(md5, hashstr1, strlen(hashstr1)); diff --git a/libavformat/sdp.c b/libavformat/sdp.c index a41c2cf655..e83616cfbe 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -216,7 +216,6 @@ static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) memcpy(p, profile_string, strlen(profile_string)); p += strlen(p); ff_data_to_hex(p, sps + 1, 3, 0); - p[6] = '\0'; } av_free(tmpbuf); @@ -340,7 +339,6 @@ static char *extradata2config(AVFormatContext *s, AVCodecParameters *par) } memcpy(config, "; config=", 9); ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0); - config[9 + par->extradata_size * 2] = 0; return config; } @@ -475,7 +473,6 @@ static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) return NULL; } ff_data_to_hex(config, config_byte, 6, 1); - config[12] = 0; return config; } diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 6bb26683b4..bb256e1190 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -122,7 +122,6 @@ static int tak_read_header(AVFormatContext *s) } ff_data_to_hex(md5_hex, md5, sizeof(md5), 1); - md5_hex[2 * sizeof(md5)] = '\0'; av_log(s, AV_LOG_VERBOSE, "MD5=%s\n", md5_hex); break; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 7840e8717c..c84f6a2348 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1151,6 +1151,7 @@ char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase) buff[i * 2] = hex_table[src[i] >> 4]; buff[i * 2 + 1] = hex_table[src[i] & 0xF]; } + buff[2 * s] = '\0'; return buff; } From 0a76f8217e0d80d336ad8d9c46523fd3d1262c8c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 19:27:15 +0100 Subject: [PATCH 415/894] avformat/aadec: Don't use the same loop counter in inner and outer loop Due to this bush.aa (from the FATE suite) exported garbage metadata with key "_040930". Signed-off-by: Andreas Rheinhardt --- libavformat/aadec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 72f4b6f7cc..a3a7664469 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -132,8 +132,8 @@ static int aa_read_header(AVFormatContext *s) AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE! } av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is "); - for (i = 0; i < 16; i++) - av_log(s, AV_LOG_DEBUG, "%02x", header_key[i]); + for (int j = 0; j < 16; j++) + av_log(s, AV_LOG_DEBUG, "%02x", header_key[j]); av_log(s, AV_LOG_DEBUG, "\n"); } else { av_dict_set(&s->metadata, key, val, 0); From a0900a318a60e38ffeb14c322b09f98fcbd97c73 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 20:46:57 +0100 Subject: [PATCH 416/894] avformat/aadec: Avoid copying data around Up until now, the packets have been read in blocks of at most eight bytes at a time; then these blocks have been decrypted and copied into a buffer on the stack (that was double the size needed...). From there they have been copied to the dst packet. This commit changes this: The data is read in one go; and the decryption avoids temporary buffers, too, by making use of the fact that src and dst of av_tea_crypt() can coincide. Signed-off-by: Andreas Rheinhardt --- libavformat/aadec.c | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index a3a7664469..7e97120070 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -32,7 +32,6 @@ #include "libavutil/opt.h" #define AA_MAGIC 1469084982 /* this identifies an audible .aa file */ -#define MAX_CODEC_SECOND_SIZE 3982 #define MAX_TOC_ENTRIES 16 #define MAX_DICTIONARY_ENTRIES 128 #define TEA_BLOCK_SIZE 8 @@ -247,13 +246,9 @@ static int aa_read_header(AVFormatContext *s) static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) { - uint8_t dst[TEA_BLOCK_SIZE]; - uint8_t src[TEA_BLOCK_SIZE]; int i; - int trailing_bytes; int blocks; - uint8_t buf[MAX_CODEC_SECOND_SIZE * 2]; - int written = 0; + uint8_t *buf; int ret; AADemuxContext *c = s->priv_data; uint64_t pos = avio_tell(s->pb); @@ -272,7 +267,6 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_DEBUG, "Chapter %d (%" PRId64 " bytes)\n", c->chapter_idx, c->current_chapter_size); c->chapter_idx = c->chapter_idx + 1; avio_skip(s->pb, 4); // data start offset - pos += 8; c->current_codec_second_size = c->codec_second_size; } @@ -281,24 +275,18 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) c->current_codec_second_size = c->current_chapter_size % c->current_codec_second_size; } + ret = av_get_packet(s->pb, pkt, c->current_codec_second_size); + if (ret != c->current_codec_second_size) + return AVERROR_EOF; + + buf = pkt->data; // decrypt c->current_codec_second_size bytes + // trailing bytes are left unencrypted! blocks = c->current_codec_second_size / TEA_BLOCK_SIZE; for (i = 0; i < blocks; i++) { - ret = avio_read(s->pb, src, TEA_BLOCK_SIZE); - if (ret != TEA_BLOCK_SIZE) - return (ret < 0) ? ret : AVERROR_EOF; av_tea_init(c->tea_ctx, c->file_key, 16); - av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 1); - memcpy(buf + written, dst, TEA_BLOCK_SIZE); - written = written + TEA_BLOCK_SIZE; - } - trailing_bytes = c->current_codec_second_size % TEA_BLOCK_SIZE; - if (trailing_bytes != 0) { // trailing bytes are left unencrypted! - ret = avio_read(s->pb, src, trailing_bytes); - if (ret != trailing_bytes) - return (ret < 0) ? ret : AVERROR_EOF; - memcpy(buf + written, src, trailing_bytes); - written = written + trailing_bytes; + av_tea_crypt(c->tea_ctx, buf, buf, 1, NULL, 1); + buf += TEA_BLOCK_SIZE; } // update state @@ -306,16 +294,12 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) if (c->current_chapter_size <= 0) c->current_chapter_size = 0; - if (c->seek_offset > written) + if (c->seek_offset > c->current_codec_second_size) c->seek_offset = 0; // ignore wrong estimate - - ret = av_new_packet(pkt, written - c->seek_offset); - if (ret < 0) - return ret; - memcpy(pkt->data, buf + c->seek_offset, written - c->seek_offset); - pkt->pos = pos; - + pkt->data += c->seek_offset; + pkt->size -= c->seek_offset; c->seek_offset = 0; + return 0; } From c9b30992102bbc4120b5c0139d1aa8a2dbb2ebb0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 21:08:06 +0100 Subject: [PATCH 417/894] avformat/aadec: Don't unnecessarily reinitialize AVTEA context We use ECB, not CBC mode here, so one does not need to reinitialize the context; for the same reason, one can also just let av_tea_crypt() loop over the blocks, avoiding a loop here. Signed-off-by: Andreas Rheinhardt --- libavformat/aadec.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 7e97120070..24116b1f70 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -173,6 +173,7 @@ static int aa_read_header(AVFormatContext *s) for (i = 0; i < 16; i++) av_log(s, AV_LOG_DEBUG, "%02x", c->file_key[i]); av_log(s, AV_LOG_DEBUG, "\n"); + av_tea_init(c->tea_ctx, c->file_key, 16); /* decoder setup */ st = avformat_new_stream(s, NULL); @@ -246,9 +247,6 @@ static int aa_read_header(AVFormatContext *s) static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) { - int i; - int blocks; - uint8_t *buf; int ret; AADemuxContext *c = s->priv_data; uint64_t pos = avio_tell(s->pb); @@ -279,15 +277,10 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret != c->current_codec_second_size) return AVERROR_EOF; - buf = pkt->data; - // decrypt c->current_codec_second_size bytes + // decrypt c->current_codec_second_size bytes in blocks of TEA_BLOCK_SIZE // trailing bytes are left unencrypted! - blocks = c->current_codec_second_size / TEA_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - av_tea_init(c->tea_ctx, c->file_key, 16); - av_tea_crypt(c->tea_ctx, buf, buf, 1, NULL, 1); - buf += TEA_BLOCK_SIZE; - } + av_tea_crypt(c->tea_ctx, pkt->data, pkt->data, + c->current_codec_second_size / TEA_BLOCK_SIZE, NULL, 1); // update state c->current_chapter_size = c->current_chapter_size - c->current_codec_second_size; From d27b97b04321db147cf7db6fa9cb05ba7f6ef06f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 22:47:27 +0100 Subject: [PATCH 418/894] avformat/aadec: Simplify deriving file key Don't use different src and dst in av_tea_crypt(); use in-place modifications instead. Also let av_tea_crypt() encrypt all three blocks in one call. Signed-off-by: Andreas Rheinhardt --- libavformat/aadec.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 24116b1f70..5f49a543e4 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -71,10 +71,10 @@ static int get_second_size(char *codec_name) static int aa_read_header(AVFormatContext *s) { - int i, j, idx, largest_idx = -1; + int i, idx, largest_idx = -1; uint32_t toc_size, npairs, header_seed = 0, start; char codec_name[64] = {0}; - uint8_t output[24], dst[8], src[8]; + uint8_t buf[24]; int64_t largest_size = -1, current_size = -1, chapter_pos; struct toc_entry { uint32_t offset; @@ -156,19 +156,11 @@ static int aa_read_header(AVFormatContext *s) if (!c->tea_ctx) return AVERROR(ENOMEM); av_tea_init(c->tea_ctx, c->aa_fixed_key, 16); - output[0] = output[1] = 0; // purely for padding purposes - memcpy(output + 2, header_key, 16); - idx = 0; - for (i = 0; i < 3; i++) { // TEA CBC with weird mixed endianness - AV_WB32(src, header_seed); - AV_WB32(src + 4, header_seed + 1); - header_seed += 2; - av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 0); // TEA ECB encrypt - for (j = 0; j < TEA_BLOCK_SIZE && idx < 18; j+=1, idx+=1) { - output[idx] = output[idx] ^ dst[j]; - } - } - memcpy(c->file_key, output + 2, 16); // skip first 2 bytes of output + for (int i = 0; i < 6; i++) + AV_WB32(buf + 4 * i, header_seed + i); + av_tea_crypt(c->tea_ctx, buf, buf, 3, NULL, 0); + AV_WN64(c->file_key, AV_RN64(buf + 2) ^ AV_RN64(header_key)); + AV_WN64(c->file_key + 8, AV_RN64(buf + 10) ^ AV_RN64(header_key + 8)); av_log(s, AV_LOG_DEBUG, "File key is "); for (i = 0; i < 16; i++) av_log(s, AV_LOG_DEBUG, "%02x", c->file_key[i]); From e5ba554edf961e1ff761d68d4ebf5a7ea4e5a3b7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 5 Dec 2021 23:04:35 +0100 Subject: [PATCH 419/894] avformat/aadec: Simplify data->hex conversion Signed-off-by: Andreas Rheinhardt --- libavformat/aadec.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 5f49a543e4..840a9968c6 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -83,6 +83,7 @@ static int aa_read_header(AVFormatContext *s) uint32_t header_key_part[4]; uint8_t header_key[16] = {0}; AADemuxContext *c = s->priv_data; + char file_key[2 * sizeof(c->file_key) + 1]; AVIOContext *pb = s->pb; AVStream *st; FFStream *sti; @@ -130,10 +131,8 @@ static int aa_read_header(AVFormatContext *s) for (idx = 0; idx < 4; idx++) { AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE! } - av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is "); - for (int j = 0; j < 16; j++) - av_log(s, AV_LOG_DEBUG, "%02x", header_key[j]); - av_log(s, AV_LOG_DEBUG, "\n"); + ff_data_to_hex(key, header_key, sizeof(header_key), 1); + av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is %s\n", key); } else { av_dict_set(&s->metadata, key, val, 0); } @@ -161,10 +160,8 @@ static int aa_read_header(AVFormatContext *s) av_tea_crypt(c->tea_ctx, buf, buf, 3, NULL, 0); AV_WN64(c->file_key, AV_RN64(buf + 2) ^ AV_RN64(header_key)); AV_WN64(c->file_key + 8, AV_RN64(buf + 10) ^ AV_RN64(header_key + 8)); - av_log(s, AV_LOG_DEBUG, "File key is "); - for (i = 0; i < 16; i++) - av_log(s, AV_LOG_DEBUG, "%02x", c->file_key[i]); - av_log(s, AV_LOG_DEBUG, "\n"); + ff_data_to_hex(file_key, c->file_key, sizeof(c->file_key), 1); + av_log(s, AV_LOG_DEBUG, "File key is %s\n", file_key); av_tea_init(c->tea_ctx, c->file_key, 16); /* decoder setup */ From 72745beb44b4ddf60b77833b2edddf80e8f79ef2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 6 Dec 2021 01:14:00 +0100 Subject: [PATCH 420/894] avformat/aadec: Use smaller scope for variables Signed-off-by: Andreas Rheinhardt --- libavformat/aadec.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 840a9968c6..b8a5428f1f 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -71,7 +71,7 @@ static int get_second_size(char *codec_name) static int aa_read_header(AVFormatContext *s) { - int i, idx, largest_idx = -1; + int largest_idx = -1; uint32_t toc_size, npairs, header_seed = 0, start; char codec_name[64] = {0}; uint8_t buf[24]; @@ -80,7 +80,6 @@ static int aa_read_header(AVFormatContext *s) uint32_t offset; uint32_t size; } TOC[MAX_TOC_ENTRIES]; - uint32_t header_key_part[4]; uint8_t header_key[16] = {0}; AADemuxContext *c = s->priv_data; char file_key[2 * sizeof(c->file_key) + 1]; @@ -96,7 +95,7 @@ static int aa_read_header(AVFormatContext *s) avio_skip(pb, 4); // unidentified integer if (toc_size > MAX_TOC_ENTRIES || toc_size < 2) return AVERROR_INVALIDDATA; - for (i = 0; i < toc_size; i++) { // read TOC + for (uint32_t i = 0; i < toc_size; i++) { // read TOC avio_skip(pb, 4); // TOC entry index TOC[i].offset = avio_rb32(pb); // block offset TOC[i].size = avio_rb32(pb); // block size @@ -105,7 +104,7 @@ static int aa_read_header(AVFormatContext *s) npairs = avio_rb32(pb); // read dictionary entries if (npairs > MAX_DICTIONARY_ENTRIES) return AVERROR_INVALIDDATA; - for (i = 0; i < npairs; i++) { + for (uint32_t i = 0; i < npairs; i++) { char key[128], val[128]; uint32_t nkey, nval; @@ -121,6 +120,7 @@ static int aa_read_header(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "HeaderSeed is <%s>\n", val); header_seed = atoi(val); } else if (!strcmp(key, "HeaderKey")) { // this looks like "1234567890 1234567890 1234567890 1234567890" + uint32_t header_key_part[4]; av_log(s, AV_LOG_DEBUG, "HeaderKey is <%s>\n", val); ret = sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32, @@ -128,9 +128,8 @@ static int aa_read_header(AVFormatContext *s) if (ret != 4) return AVERROR_INVALIDDATA; - for (idx = 0; idx < 4; idx++) { + for (int idx = 0; idx < 4; idx++) AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE! - } ff_data_to_hex(key, header_key, sizeof(header_key), 1); av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is %s\n", key); } else { @@ -195,7 +194,7 @@ static int aa_read_header(AVFormatContext *s) } /* determine, and jump to audio start offset */ - for (i = 1; i < toc_size; i++) { // skip the first entry! + for (uint32_t i = 1; i < toc_size; i++) { // skip the first entry! current_size = TOC[i].size; if (current_size > largest_size) { largest_idx = i; From fbbe7729f0fc7db3daad584b0e5f5a898f2b8acf Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 6 Dec 2021 01:14:28 +0100 Subject: [PATCH 421/894] avutil/aes_ctr: Avoid allocation of AVAES struct Signed-off-by: Andreas Rheinhardt --- libavutil/aes_ctr.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libavutil/aes_ctr.c b/libavutil/aes_ctr.c index 0c2e86785f..517d09cf96 100644 --- a/libavutil/aes_ctr.c +++ b/libavutil/aes_ctr.c @@ -22,15 +22,16 @@ #include "common.h" #include "aes_ctr.h" #include "aes.h" +#include "aes_internal.h" #include "random_seed.h" #define AES_BLOCK_SIZE (16) typedef struct AVAESCTR { - struct AVAES* aes; uint8_t counter[AES_BLOCK_SIZE]; uint8_t encrypted_counter[AES_BLOCK_SIZE]; int block_offset; + AVAES aes; } AVAESCTR; struct AVAESCTR *av_aes_ctr_alloc(void) @@ -68,12 +69,7 @@ void av_aes_ctr_set_random_iv(struct AVAESCTR *a) int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key) { - a->aes = av_aes_alloc(); - if (!a->aes) { - return AVERROR(ENOMEM); - } - - av_aes_init(a->aes, key, 128, 0); + av_aes_init(&a->aes, key, 128, 0); memset(a->counter, 0, sizeof(a->counter)); a->block_offset = 0; @@ -83,10 +79,7 @@ int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key) void av_aes_ctr_free(struct AVAESCTR *a) { - if (a) { - av_freep(&a->aes); - av_free(a); - } + av_free(a); } static void av_aes_ctr_increment_be64(uint8_t* counter) @@ -116,7 +109,7 @@ void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int while (src < src_end) { if (a->block_offset == 0) { - av_aes_crypt(a->aes, a->encrypted_counter, a->counter, 1, NULL, 0); + av_aes_crypt(&a->aes, a->encrypted_counter, a->counter, 1, NULL, 0); av_aes_ctr_increment_be64(a->counter + 8); } From d203f6b4b33be409c85d5319f6cd253829334f45 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 6 Dec 2021 01:25:06 +0100 Subject: [PATCH 422/894] avformat/md5proto: Simplify data->hex conversion Signed-off-by: Andreas Rheinhardt --- libavformat/md5proto.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c index 0e04b90aac..14cefe719c 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -25,6 +25,7 @@ #include "libavutil/error.h" #include "avformat.h" #include "avio.h" +#include "internal.h" #include "url.h" struct MD5Context { @@ -57,14 +58,13 @@ static int md5_close(URLContext *h) { struct MD5Context *c = h->priv_data; const char *filename = h->filename; - uint8_t md5[16], buf[64]; + uint8_t md5[16], buf[2 * sizeof(md5) + 1]; URLContext *out; - int i, err = 0; + int err = 0; av_md5_final(c->md5, md5); - for (i = 0; i < sizeof(md5); i++) - snprintf(buf + i*2, 3, "%02x", md5[i]); - buf[i*2] = '\n'; + ff_data_to_hex(buf, md5, sizeof(md5), 1); + buf[2 * sizeof(md5)] = '\n'; av_strstart(filename, "md5:", &filename); @@ -74,10 +74,10 @@ static int md5_close(URLContext *h) h->protocol_whitelist, h->protocol_blacklist, h); if (err) return err; - err = ffurl_write(out, buf, i*2+1); + err = ffurl_write(out, buf, sizeof(buf)); ffurl_close(out); } else { - if (fwrite(buf, 1, i*2+1, stdout) < i*2+1) + if (fwrite(buf, 1, sizeof(buf), stdout) < sizeof(buf)) err = AVERROR(errno); } From 17a93fd3772269cf3978783ddca90e3ba037cb81 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 6 Dec 2021 01:42:46 +0100 Subject: [PATCH 423/894] avformat/mov: Simplify data->hex conversion Signed-off-by: Andreas Rheinhardt --- libavformat/mov.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index ff5a55d0e6..9ebfa0bcc7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -979,6 +979,7 @@ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom) uint8_t output[64]; uint8_t file_checksum[20]; uint8_t calculated_checksum[20]; + char checksum_string[2 * sizeof(file_checksum) + 1]; struct AVSHA *sha; int i; int ret = 0; @@ -1003,10 +1004,9 @@ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d avio_read(pb, file_checksum, 20); - av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == "); // required by external tools - for (i = 0; i < 20; i++) - av_log(c->fc, AV_LOG_INFO, "%02x", file_checksum[i]); - av_log(c->fc, AV_LOG_INFO, "\n"); + // required by external tools + ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1); + av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string); /* verify activation data */ if (!activation_bytes) { From 683bbb75dbeaae9feff08f81f8df573229544a2d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 7 Dec 2021 19:44:44 +0100 Subject: [PATCH 424/894] avcodec/movtextdec: Rename several structure elements Giving elements of a structure called StyleBox names like "style_start" or "style_end" is redundant, especially given that the relevant variables are also called style. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 4e14ae5900..7021ad9e24 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -54,7 +54,7 @@ #define RGB_TO_BGR(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff)) typedef struct { - uint16_t fontID; + uint16_t font_id; const char *font; uint8_t fontsize; int color; @@ -68,21 +68,21 @@ typedef struct { } MovTextDefault; typedef struct { - uint16_t fontID; + uint16_t font_id; char *font; } FontRecord; typedef struct { - uint16_t style_start; - uint16_t style_end; - uint8_t style_flag; + uint16_t start; + uint16_t end; + uint8_t flags; uint8_t bold; uint8_t italic; uint8_t underline; int color; uint8_t alpha; uint8_t fontsize; - uint16_t style_fontID; + uint16_t font_id; } StyleBox; typedef struct { @@ -186,12 +186,12 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) // StyleRecord tx3g_ptr += 4; // fontID - m->d.fontID = bytestream_get_be16(&tx3g_ptr); + m->d.font_id = bytestream_get_be16(&tx3g_ptr); // face-style-flags - s_default.style_flag = bytestream_get_byte(&tx3g_ptr); - m->d.bold = !!(s_default.style_flag & STYLE_FLAG_BOLD); - m->d.italic = !!(s_default.style_flag & STYLE_FLAG_ITALIC); - m->d.underline = !!(s_default.style_flag & STYLE_FLAG_UNDERLINE); + s_default.flags = bytestream_get_byte(&tx3g_ptr); + m->d.bold = !!(s_default.flags & STYLE_FLAG_BOLD); + m->d.italic = !!(s_default.flags & STYLE_FLAG_ITALIC); + m->d.underline = !!(s_default.flags & STYLE_FLAG_UNDERLINE); // fontsize m->d.fontsize = bytestream_get_byte(&tx3g_ptr); // Primary color @@ -218,8 +218,8 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) m->ftab_entries = ftab_entries; for (i = 0; i < m->ftab_entries; i++) { - m->ftab[i].fontID = bytestream_get_be16(&tx3g_ptr); - if (m->ftab[i].fontID == m->d.fontID) + m->ftab[i].font_id = bytestream_get_be16(&tx3g_ptr); + if (m->ftab[i].font_id == m->d.font_id) j = i; font_length = bytestream_get_byte(&tx3g_ptr); @@ -283,14 +283,14 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a for(i = 0; i < m->style_entries; i++) { StyleBox *style = &m->s[i]; - style->style_start = bytestream_get_be16(&tsmb); - style->style_end = bytestream_get_be16(&tsmb); - if ( style->style_end < style->style_start - || (i && style->style_start < m->s[i - 1].style_end)) { + style->start = bytestream_get_be16(&tsmb); + style->end = bytestream_get_be16(&tsmb); + if (style->end < style->start || + (i && style->start < m->s[i - 1].end)) { mov_text_cleanup(m); return AVERROR(ENOMEM); } - if (style->style_start == style->style_end) { + if (style->start == style->end) { /* Skip this style as it applies to no character */ tsmb += 8; m->style_entries--; @@ -298,11 +298,11 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a continue; } - style->style_fontID = bytestream_get_be16(&tsmb); - style->style_flag = bytestream_get_byte(&tsmb); - style->bold = !!(style->style_flag & STYLE_FLAG_BOLD); - style->italic = !!(style->style_flag & STYLE_FLAG_ITALIC); - style->underline = !!(style->style_flag & STYLE_FLAG_UNDERLINE); + style->font_id = bytestream_get_be16(&tsmb); + style->flags = bytestream_get_byte(&tsmb); + style->bold = !!(style->flags & STYLE_FLAG_BOLD); + style->italic = !!(style->flags & STYLE_FLAG_ITALIC); + style->underline = !!(style->flags & STYLE_FLAG_UNDERLINE); style->fontsize = bytestream_get_byte(&tsmb); style->color = bytestream_get_be24(&tsmb); style->alpha = bytestream_get_byte(&tsmb); @@ -355,13 +355,13 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, if ((m->box_flags & STYL_BOX) && entry < m->style_entries) { const StyleBox *style = &m->s[entry]; - if (text_pos == style->style_end) { + if (text_pos == style->end) { av_bprintf(buf, "{\\r}"); color = m->d.color; entry++; style++; } - if (entry < m->style_entries && text_pos == style->style_start) { + if (entry < m->style_entries && text_pos == style->start) { if (style->bold ^ m->d.bold) av_bprintf(buf, "{\\b%d}", style->bold); if (style->italic ^ m->d.italic) @@ -370,9 +370,9 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, av_bprintf(buf, "{\\u%d}", style->underline); if (style->fontsize != m->d.fontsize) av_bprintf(buf, "{\\fs%d}", style->fontsize); - if (style->style_fontID != m->d.fontID) + if (style->font_id != m->d.font_id) for (i = 0; i < m->ftab_entries; i++) { - if (style->style_fontID == m->ftab[i].fontID) + if (style->font_id == m->ftab[i].font_id) av_bprintf(buf, "{\\fn%s}", m->ftab[i].font); } if (m->d.color != style->color) { From 4b2bc0b8fed9fb464b85fe53b8d49b570b0c9c9e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 7 Dec 2021 20:42:25 +0100 Subject: [PATCH 425/894] avcodec/movtextdec: Deduplicate parsing of StyleRecords Both TextSampleEntry and TextSample can contain StyleRecords; yet both the code as well as the structures for them were duplicated. This commit changes this. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 95 +++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 51 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 7021ad9e24..d3b15d07f8 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -53,20 +53,6 @@ #define RGB_TO_BGR(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff)) -typedef struct { - uint16_t font_id; - const char *font; - uint8_t fontsize; - int color; - uint8_t alpha; - int back_color; - uint8_t back_alpha; - uint8_t bold; - uint8_t italic; - uint8_t underline; - int alignment; -} MovTextDefault; - typedef struct { uint16_t font_id; char *font; @@ -85,6 +71,14 @@ typedef struct { uint16_t font_id; } StyleBox; +typedef struct { + StyleBox style; + const char *font; + int back_color; + uint8_t back_alpha; + int alignment; +} MovTextDefault; + typedef struct { uint16_t hlit_start; uint16_t hlit_end; @@ -137,13 +131,28 @@ static void mov_text_cleanup_ftab(MovTextContext *m) m->ftab_entries = 0; } +static void mov_text_parse_style_record(StyleBox *style, const uint8_t **ptr) +{ + // fontID + style->font_id = bytestream_get_be16(ptr); + // face-style-flags + style->flags = bytestream_get_byte(ptr); + style->bold = !!(style->flags & STYLE_FLAG_BOLD); + style->italic = !!(style->flags & STYLE_FLAG_ITALIC); + style->underline = !!(style->flags & STYLE_FLAG_UNDERLINE); + // fontsize + style->fontsize = bytestream_get_byte(ptr); + // Primary color + style->color = bytestream_get_be24(ptr); + style->alpha = bytestream_get_byte(ptr); +} + static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) { const uint8_t *tx3g_ptr = avctx->extradata; int i, j = -1, font_length, remaining = avctx->extradata_size - BOX_SIZE_INITIAL; int8_t v_align, h_align; unsigned ftab_entries; - StyleBox s_default; m->ftab_entries = 0; if (remaining < 0) @@ -185,18 +194,7 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) tx3g_ptr += 8; // StyleRecord tx3g_ptr += 4; - // fontID - m->d.font_id = bytestream_get_be16(&tx3g_ptr); - // face-style-flags - s_default.flags = bytestream_get_byte(&tx3g_ptr); - m->d.bold = !!(s_default.flags & STYLE_FLAG_BOLD); - m->d.italic = !!(s_default.flags & STYLE_FLAG_ITALIC); - m->d.underline = !!(s_default.flags & STYLE_FLAG_UNDERLINE); - // fontsize - m->d.fontsize = bytestream_get_byte(&tx3g_ptr); - // Primary color - m->d.color = bytestream_get_be24(&tx3g_ptr); - m->d.alpha = bytestream_get_byte(&tx3g_ptr); + mov_text_parse_style_record(&m->d.style, &tx3g_ptr); // FontRecord // FontRecord Size tx3g_ptr += 4; @@ -219,7 +217,7 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) for (i = 0; i < m->ftab_entries; i++) { m->ftab[i].font_id = bytestream_get_be16(&tx3g_ptr); - if (m->ftab[i].font_id == m->d.font_id) + if (m->ftab[i].font_id == m->d.style.font_id) j = i; font_length = bytestream_get_byte(&tx3g_ptr); @@ -298,14 +296,7 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a continue; } - style->font_id = bytestream_get_be16(&tsmb); - style->flags = bytestream_get_byte(&tsmb); - style->bold = !!(style->flags & STYLE_FLAG_BOLD); - style->italic = !!(style->flags & STYLE_FLAG_ITALIC); - style->underline = !!(style->flags & STYLE_FLAG_UNDERLINE); - style->fontsize = bytestream_get_byte(&tsmb); - style->color = bytestream_get_be24(&tsmb); - style->alpha = bytestream_get_byte(&tsmb); + mov_text_parse_style_record(style, &tsmb); } return 0; } @@ -337,10 +328,11 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, AVCodecContext *avctx) { MovTextContext *m = avctx->priv_data; + const StyleBox *const default_style = &m->d.style; int i = 0; int text_pos = 0; int entry = 0; - int color = m->d.color; + int color = default_style->color; if (text < text_end && m->box_flags & TWRP_BOX) { if (m->w.wrap_flag == 1) { @@ -357,29 +349,29 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, const StyleBox *style = &m->s[entry]; if (text_pos == style->end) { av_bprintf(buf, "{\\r}"); - color = m->d.color; + color = default_style->color; entry++; style++; } if (entry < m->style_entries && text_pos == style->start) { - if (style->bold ^ m->d.bold) + if (style->bold ^ default_style->bold) av_bprintf(buf, "{\\b%d}", style->bold); - if (style->italic ^ m->d.italic) + if (style->italic ^ default_style->italic) av_bprintf(buf, "{\\i%d}", style->italic); - if (style->underline ^ m->d.underline) + if (style->underline ^ default_style->underline) av_bprintf(buf, "{\\u%d}", style->underline); - if (style->fontsize != m->d.fontsize) + if (style->fontsize != default_style->fontsize) av_bprintf(buf, "{\\fs%d}", style->fontsize); - if (style->font_id != m->d.font_id) + if (style->font_id != default_style->font_id) for (i = 0; i < m->ftab_entries; i++) { if (style->font_id == m->ftab[i].font_id) av_bprintf(buf, "{\\fn%s}", m->ftab[i].font); } - if (m->d.color != style->color) { + if (default_style->color != style->color) { color = style->color; av_bprintf(buf, "{\\1c&H%X&}", RGB_TO_BGR(color)); } - if (m->d.alpha != style->alpha) + if (default_style->alpha != style->alpha) av_bprintf(buf, "{\\1a&H%02X&}", 255 - style->alpha); } } @@ -400,10 +392,10 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, } if (text_pos == m->h.hlit_end) { if (m->box_flags & HCLR_BOX) { - av_bprintf(buf, "{\\2c&H%X&}", RGB_TO_BGR(m->d.color)); + av_bprintf(buf, "{\\2c&H%X&}", RGB_TO_BGR(default_style->color)); } else { av_bprintf(buf, "{\\1c&H%X&}{\\2c&H%X&}", - RGB_TO_BGR(color), RGB_TO_BGR(m->d.color)); + RGB_TO_BGR(color), RGB_TO_BGR(default_style->color)); } } } @@ -441,18 +433,19 @@ static int mov_text_init(AVCodecContext *avctx) { MovTextContext *m = avctx->priv_data; ret = mov_text_tx3g(avctx, m); if (ret == 0) { + const StyleBox *const default_style = &m->d.style; if (!m->frame_width || !m->frame_height) { m->frame_width = ASS_DEFAULT_PLAYRESX; m->frame_height = ASS_DEFAULT_PLAYRESY; } return ff_ass_subtitle_header_full(avctx, m->frame_width, m->frame_height, - m->d.font, m->d.fontsize, - (255U - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color), - (255U - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color), + m->d.font, default_style->fontsize, + (255U - default_style->alpha) << 24 | RGB_TO_BGR(default_style->color), + (255U - default_style->alpha) << 24 | RGB_TO_BGR(default_style->color), (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color), (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color), - m->d.bold, m->d.italic, m->d.underline, + default_style->bold, default_style->italic, default_style->underline, ASS_DEFAULT_BORDERSTYLE, m->d.alignment); } else return ff_ass_subtitle_header_default(avctx); From cce2765ce9dee0c653e725282107694ed0ed345a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 7 Dec 2021 20:57:45 +0100 Subject: [PATCH 426/894] avcodec/movtextdec: Perform RGB->BGR color conversion early Reduces the amount of conversions. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index d3b15d07f8..c50626c0b5 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -144,6 +144,7 @@ static void mov_text_parse_style_record(StyleBox *style, const uint8_t **ptr) style->fontsize = bytestream_get_byte(ptr); // Primary color style->color = bytestream_get_be24(ptr); + style->color = RGB_TO_BGR(style->color); style->alpha = bytestream_get_byte(ptr); } @@ -189,6 +190,7 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) } // Background Color m->d.back_color = bytestream_get_be24(&tx3g_ptr); + m->d.back_color = RGB_TO_BGR(m->d.back_color); m->d.back_alpha = bytestream_get_byte(&tx3g_ptr); // BoxRecord tx3g_ptr += 8; @@ -369,7 +371,7 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, } if (default_style->color != style->color) { color = style->color; - av_bprintf(buf, "{\\1c&H%X&}", RGB_TO_BGR(color)); + av_bprintf(buf, "{\\1c&H%X&}", color); } if (default_style->alpha != style->alpha) av_bprintf(buf, "{\\1a&H%02X&}", 255 - style->alpha); @@ -392,10 +394,10 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, } if (text_pos == m->h.hlit_end) { if (m->box_flags & HCLR_BOX) { - av_bprintf(buf, "{\\2c&H%X&}", RGB_TO_BGR(default_style->color)); + av_bprintf(buf, "{\\2c&H%X&}", default_style->color); } else { av_bprintf(buf, "{\\1c&H%X&}{\\2c&H%X&}", - RGB_TO_BGR(color), RGB_TO_BGR(default_style->color)); + color, default_style->color); } } } @@ -441,10 +443,10 @@ static int mov_text_init(AVCodecContext *avctx) { return ff_ass_subtitle_header_full(avctx, m->frame_width, m->frame_height, m->d.font, default_style->fontsize, - (255U - default_style->alpha) << 24 | RGB_TO_BGR(default_style->color), - (255U - default_style->alpha) << 24 | RGB_TO_BGR(default_style->color), - (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color), - (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color), + (255U - default_style->alpha) << 24 | default_style->color, + (255U - default_style->alpha) << 24 | default_style->color, + (255U - m->d.back_alpha) << 24 | m->d.back_color, + (255U - m->d.back_alpha) << 24 | m->d.back_color, default_style->bold, default_style->italic, default_style->underline, ASS_DEFAULT_BORDERSTYLE, m->d.alignment); } else From cc1251ab814374ffb27cdebf2099b11a422d8187 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 7 Dec 2021 22:23:47 +0100 Subject: [PATCH 427/894] avcodec/movtextdec: Sanitize style entries There are three types of style entries which are redundant: a) Entries with length zero. They are already discarded. b) Entries that are equivalent to the default style: They can be safely discarded. c) Entries that are equivalent to the immediately preceding style if the start of the current style coincides with the end of the preceding style. In this case the styles can be merged. This commit implements discarding/merging in cases b) and c). This fixes ticket #9548. In said ticket each packet contained exactly one style entry that covered the complete packet with the exception of the last character (probably created by a tool that didn't know that the style's end is exclusive). Said style coincided with the default style, leading to a superfluous reset, which is now gone. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index c50626c0b5..b0c54bf1d0 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -263,6 +263,14 @@ static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a return 0; } +static int styles_equivalent(const StyleBox *a, const StyleBox *b) +{ +#define CMP(field) a->field == b->field + return CMP(bold) && CMP(italic) && CMP(underline) && CMP(color) && + CMP(alpha) && CMP(fontsize) && CMP(font_id); +#undef CMP +} + static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) { int i; @@ -299,6 +307,19 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a } mov_text_parse_style_record(style, &tsmb); + if (styles_equivalent(style, &m->d.style)) { + /* Skip this style as it is equivalent to the default style */ + m->style_entries--; + i--; + continue; + } else if (i && style->start == style[-1].end && + styles_equivalent(style, &style[-1])) { + /* Merge the two adjacent styles */ + style[-1].end = style->end; + m->style_entries--; + i--; + continue; + } } return 0; } From b51d772a50c94804a860904f2e14afeca4ca093e Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 26 Nov 2021 19:38:22 +0800 Subject: [PATCH 428/894] avcodec/bitpacked_dec: remove AV_CODEC_CAP_EXPERIMENTAL capabilities Signed-off-by: Limin Wang --- libavcodec/bitpacked_dec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/bitpacked_dec.c b/libavcodec/bitpacked_dec.c index 0440df9261..c1cb6acefe 100644 --- a/libavcodec/bitpacked_dec.c +++ b/libavcodec/bitpacked_dec.c @@ -149,7 +149,6 @@ const AVCodec ff_bitpacked_decoder = { .priv_data_size = sizeof(struct BitpackedContext), .init = bitpacked_init_decoder, .decode = bitpacked_decode, - .capabilities = AV_CODEC_CAP_EXPERIMENTAL, .codec_tags = (const uint32_t []){ MKTAG('U', 'Y', 'V', 'Y'), FF_CODEC_TAGS_END, From 17b434f1ce0bb1687460ee5539fa8038bbc9018c Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 26 Nov 2021 19:49:01 +0800 Subject: [PATCH 429/894] avcodec/bitpacked_dec: setting pict_type and key_frame after decode() Signed-off-by: Limin Wang --- libavcodec/bitpacked_dec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/bitpacked_dec.c b/libavcodec/bitpacked_dec.c index c1cb6acefe..a2edccc43c 100644 --- a/libavcodec/bitpacked_dec.c +++ b/libavcodec/bitpacked_dec.c @@ -129,13 +129,13 @@ static int bitpacked_decode(AVCodecContext *avctx, void *data, int *got_frame, AVFrame *frame = data; int res; - frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; - res = bc->decode(avctx, frame, avpkt); if (res) return res; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; return buf_size; From d39f667da155054307e143dc23b225ca88a59dc9 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 26 Nov 2021 20:20:15 +0800 Subject: [PATCH 430/894] avcodec/bitpacked_dec: support for frame thread decode Signed-off-by: Limin Wang --- libavcodec/bitpacked_dec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/bitpacked_dec.c b/libavcodec/bitpacked_dec.c index a2edccc43c..69fea9c366 100644 --- a/libavcodec/bitpacked_dec.c +++ b/libavcodec/bitpacked_dec.c @@ -30,6 +30,7 @@ #include "internal.h" #include "get_bits.h" #include "libavutil/imgutils.h" +#include "thread.h" struct BitpackedContext { int (*decode)(AVCodecContext *avctx, AVFrame *frame, @@ -64,11 +65,12 @@ static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame, { uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 20; uint64_t packet_size = (uint64_t)avpkt->size * 8; + ThreadFrame tframe = { .f = frame }; GetBitContext bc; uint16_t *y, *u, *v; int ret, i, j; - ret = ff_get_buffer(avctx, frame, 0); + ret = ff_thread_get_buffer(avctx, &tframe, 0); if (ret < 0) return ret; @@ -149,6 +151,7 @@ const AVCodec ff_bitpacked_decoder = { .priv_data_size = sizeof(struct BitpackedContext), .init = bitpacked_init_decoder, .decode = bitpacked_decode, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .codec_tags = (const uint32_t []){ MKTAG('U', 'Y', 'V', 'Y'), FF_CODEC_TAGS_END, From b9f4c1231f8f07d8e62114b6d14f6aa064d19f43 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 26 Nov 2021 20:42:03 +0800 Subject: [PATCH 431/894] avcodec/bitpacked_enc: suppport for frame thread encode Signed-off-by: Limin Wang --- libavcodec/bitpacked_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/bitpacked_enc.c b/libavcodec/bitpacked_enc.c index 3e0ba0055e..6f540f1aed 100644 --- a/libavcodec/bitpacked_enc.c +++ b/libavcodec/bitpacked_enc.c @@ -109,7 +109,7 @@ const AVCodec ff_bitpacked_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_BITPACKED, .priv_data_size = sizeof(struct BitpackedContext), - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init = encode_init, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, From a33e0ed11e72c9463dcfee240aa7cf5c2a57b102 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 7 Dec 2021 10:37:53 +0100 Subject: [PATCH 432/894] avformat/utils: Fix wrong indentation Signed-off-by: Andreas Rheinhardt --- libavformat/utils.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index c84f6a2348..5b4156cad8 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1480,23 +1480,23 @@ static int match_stream_specifier(AVFormatContext *s, AVStream *st, int ret; if (match) { - spec += 2; - val = strchr(spec, ':'); + spec += 2; + val = strchr(spec, ':'); - key = val ? av_strndup(spec, val - spec) : av_strdup(spec); - if (!key) - return AVERROR(ENOMEM); + key = val ? av_strndup(spec, val - spec) : av_strdup(spec); + if (!key) + return AVERROR(ENOMEM); - tag = av_dict_get(st->metadata, key, NULL, 0); - if (tag) { - if (!val || !strcmp(tag->value, val + 1)) - ret = 1; - else - ret = 0; - } else - ret = 0; + tag = av_dict_get(st->metadata, key, NULL, 0); + if (tag) { + if (!val || !strcmp(tag->value, val + 1)) + ret = 1; + else + ret = 0; + } else + ret = 0; - av_freep(&key); + av_freep(&key); } return match && ret; } else if (*spec == 'u' && *(spec + 1) == '\0') { From 408b974796c55a3a2ca0bba2c3ac473e0bdfcd3f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 7 Dec 2021 10:54:33 +0100 Subject: [PATCH 433/894] avformat/utils: Add const where appropriate Signed-off-by: Andreas Rheinhardt --- libavformat/internal.h | 2 +- libavformat/utils.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index f43e408548..878c4f1164 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -630,7 +630,7 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, * Find stream index based on format-specific stream ID * @return stream index, or < 0 on error */ -int ff_find_stream_index(AVFormatContext *s, int id); +int ff_find_stream_index(const AVFormatContext *s, int id); /** * Internal version of av_index_search_timestamp diff --git a/libavformat/utils.c b/libavformat/utils.c index 5b4156cad8..c368b60864 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1264,7 +1264,7 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, } } -int ff_find_stream_index(AVFormatContext *s, int id) +int ff_find_stream_index(const AVFormatContext *s, int id) { for (unsigned i = 0; i < s->nb_streams; i++) if (s->streams[i]->id == id) @@ -1407,8 +1407,9 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f * 0 if st is NOT a matching stream * >0 if st is a matching stream */ -static int match_stream_specifier(AVFormatContext *s, AVStream *st, - const char *spec, const char **indexptr, AVProgram **p) +static int match_stream_specifier(const AVFormatContext *s, const AVStream *st, + const char *spec, const char **indexptr, + const AVProgram **p) { int match = 1; /* Stores if the specifier matches so far. */ while (*spec) { @@ -1475,7 +1476,7 @@ static int match_stream_specifier(AVFormatContext *s, AVStream *st, return AVERROR(EINVAL); return match && (stream_id == st->id); } else if (*spec == 'm' && *(spec + 1) == ':') { - AVDictionaryEntry *tag; + const AVDictionaryEntry *tag; char *key, *val; int ret; @@ -1500,7 +1501,7 @@ static int match_stream_specifier(AVFormatContext *s, AVStream *st, } return match && ret; } else if (*spec == 'u' && *(spec + 1) == '\0') { - AVCodecParameters *par = st->codecpar; + const AVCodecParameters *par = st->codecpar; int val; switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -1536,7 +1537,7 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, int ret, index; char *endptr; const char *indexptr = NULL; - AVProgram *p = NULL; + const AVProgram *p = NULL; int nb_streams; ret = match_stream_specifier(s, st, spec, &indexptr, &p); @@ -1559,7 +1560,7 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, /* If we requested a matching stream index, we have to ensure st is that. */ nb_streams = p ? p->nb_stream_indexes : s->nb_streams; for (int i = 0; i < nb_streams && index >= 0; i++) { - AVStream *candidate = p ? s->streams[p->stream_index[i]] : s->streams[i]; + const AVStream *candidate = s->streams[p ? p->stream_index[i] : i]; ret = match_stream_specifier(s, candidate, spec, NULL, NULL); if (ret < 0) goto error; From ac2b34abbf93c1fa11ee7e5667ce6e6d4c4760a2 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 8 Dec 2021 11:17:13 +0800 Subject: [PATCH 434/894] libswresample/swresamplec: Err num(negative-size) was used as a function parameter If memory allocation fails, ERROR(ENOMEM) '-12' will be returned. When resample() is done first, the negative size param would cause buffer-overflow and SEGV in swri_rematrix(). When swri_rematrix() is run first, resample() would not cause an error but Err num as a wrong parameter passing. Err num should be returned immediately. And remove an unneeded term from an assert. coredump info: #0 0x499517 in posix_memalign (/home/r1/ffmpeg/ffmpeg_4.4.1+0x499517) #1 0x6c1f0b4 in av_malloc /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavutil/mem.c:86:9 #2 0x6c208fe in av_mallocz /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavutil/mem.c:239:17 #3 0x6c207ad in av_mallocz_array /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavutil/mem.c:195:12 #4 0x654b2e5 in swri_realloc_audio /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libswresample/swresample.c:418:14 #5 0x654f9a1 in swr_convert_internal /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libswresample/swresample.c:601:17 #6 0x654d2c0 in swr_convert /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libswresample/swresample.c:766:19 #7 0x186cf56 in flush_frame /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/af_aresample.c:251:13 #8 0x186a454 in request_frame /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/af_aresample.c:288:20 #9 0x787d9c in ff_request_frame_to_filter /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/avfilter.c:459:15 #10 0x7877f1 in forward_status_change /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/avfilter.c:1257:19 #11 0x77ed7e in ff_filter_activate_default /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/avfilter.c:1288:20 #12 0x77e4e1 in ff_filter_activate /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/avfilter.c:1441:11 #13 0x793b3f in ff_filter_graph_run_once /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/avfiltergraph.c:1403:12 #14 0x7a7bee in get_frame_internal /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/buffersink.c:131:19 #15 0x7a7287 in av_buffersink_get_frame_flags /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/buffersink.c:142:12 #16 0x792888 in avfilter_graph_request_oldest /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/libavfilter/avfiltergraph.c:1356:17 #17 0x5d07df in transcode_from_filter /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/fftools/ffmpeg.c:4639:11 #18 0x59e557 in transcode_step /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/fftools/ffmpeg.c:4729:20 #19 0x593970 in transcode /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/fftools/ffmpeg.c:4805:15 #20 0x58f7a4 in main /home/r1/ffmpeg/ffmpeg-4.4.1/build/src/fftools/ffmpeg.c:5010:9 #21 0x7f6fd2dee0b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16 SUMMARY: AddressSanitizer: negative-size-param (/home/r1/ffmpeg/ffmpeg_4.4.1+0x497e67) in __asan_memcpy Reported-by: TOTE Robot Signed-off-by: Michael Niedermayer --- libswresample/swresample.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libswresample/swresample.c b/libswresample/swresample.c index c03fe5528f..16734c9df9 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -643,14 +643,16 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(s->resample_first){ if(postin != midbuf) - out_count= resample(s, midbuf, out_count, postin, in_count); + if ((out_count = resample(s, midbuf, out_count, postin, in_count)) < 0) + return out_count; if(midbuf != preout) swri_rematrix(s, preout, midbuf, out_count, preout==out); }else{ if(postin != midbuf) swri_rematrix(s, midbuf, postin, in_count, midbuf==out); if(midbuf != preout) - out_count= resample(s, preout, out_count, midbuf, in_count); + if ((out_count = resample(s, preout, out_count, midbuf, in_count)) < 0) + return out_count; } if(preout != out && out_count){ @@ -769,7 +771,7 @@ int attribute_align_arg swr_convert(struct SwrContext *s, if(ret>0 && !s->drop_output) s->outpts += ret * (int64_t)s->in_sample_rate; - av_assert2(max_output < 0 || ret < 0 || ret <= max_output); + av_assert2(max_output < 0 || ret <= max_output); return ret; }else{ From a4af92d7cb044424d31a99fc2f8a091f882036a5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Dec 2021 22:32:57 +0100 Subject: [PATCH 435/894] avformat/mxfdec: Check component_depth in mxf_get_color_range() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: shift exponent 4294967163 is too large for 32-bit type 'int' Fixes: 41449/clusterfuzz-testcase-minimized-ffmpeg_IO_DEMUXER_fuzzer-6183636217495552 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavformat/mxfdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index af9d33f796..c231c944c0 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -2274,12 +2274,12 @@ static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *des /* CDCI range metadata */ if (!descriptor->component_depth) return AVCOL_RANGE_UNSPECIFIED; - if (descriptor->black_ref_level == 0 && + if (descriptor->black_ref_level == 0 && descriptor->component_depth < 31 && descriptor->white_ref_level == ((1<component_depth) - 1) && (descriptor->color_range == (1<component_depth) || descriptor->color_range == ((1<component_depth) - 1))) return AVCOL_RANGE_JPEG; - if (descriptor->component_depth >= 8 && + if (descriptor->component_depth >= 8 && descriptor->component_depth < 31 && descriptor->black_ref_level == (1 <<(descriptor->component_depth - 4)) && descriptor->white_ref_level == (235<<(descriptor->component_depth - 8)) && descriptor->color_range == ((14<<(descriptor->component_depth - 4)) + 1)) From 1e85a698c01133a7f8d35502d5901e3b65fa3317 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 20 Jul 2021 22:14:21 +0200 Subject: [PATCH 436/894] avcodec/targa: Do not return images when there is no image in the tga Fixes: Timeout Fixes: 35877/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TARGA_fuzzer-5407292819374080 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/targa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/targa.c b/libavcodec/targa.c index 3502636c16..221fcc956d 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -176,6 +176,10 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = ff_set_dimensions(avctx, w, h)) < 0) return ret; + if ((compr & (~TGA_RLE)) == TGA_NODATA) { + return avpkt->size; + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; @@ -242,9 +246,6 @@ static int decode_frame(AVCodecContext *avctx, } } - if ((compr & (~TGA_RLE)) == TGA_NODATA) { - memset(p->data[0], 0, p->linesize[0] * h); - } else { if (compr & TGA_RLE) { int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp, interleave); if (res < 0) @@ -289,7 +290,6 @@ static int decode_frame(AVCodecContext *avctx, } } } - } *got_frame = 1; From 0ec75723a484405eb2f2ec2f9e58161b168ed8b0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 3 Dec 2021 17:58:50 +0100 Subject: [PATCH 437/894] avcodec/apedec: Change avg to uint32_t Fixes: Integer overflow Fixes: 40973/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APE_fuzzer-6739312704618496 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Suggested-by: Anton Khirnov Signed-off-by: Michael Niedermayer --- libavcodec/apedec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 9c723f2997..35a2e617e6 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -102,7 +102,7 @@ typedef struct APEFilter { int16_t *historybuffer; ///< filter memory int16_t *delay; ///< filtered values - int avg; + uint32_t avg; } APEFilter; typedef struct APERice { From 4f44a218e53cd92e64ba10a935bc1e7583c3e218 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Dec 2021 22:19:05 +0100 Subject: [PATCH 438/894] avformat/mxfdec: Check for duplicate mxf_read_index_entry_array() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: memleak Fixes: 41596/clusterfuzz-testcase-minimized-ffmpeg_dem_MXF_fuzzer-6439060204290048 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavformat/mxfdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index c231c944c0..1d50198279 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1111,6 +1111,9 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg { int i, length; + if (segment->temporal_offset_entries) + return AVERROR_INVALIDDATA; + segment->nb_index_entries = avio_rb32(pb); length = avio_rb32(pb); From ceeff7ae8d918cd54a9b1c8deb85184da53f1250 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Thu, 9 Dec 2021 17:36:52 +0800 Subject: [PATCH 439/894] avfilter/vf_transpose: fix un-checked potential memory allocation failure Signed-off-by: Wu Jianhua --- libavfilter/vf_transpose.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index f9f0d70cd5..b964daeee3 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -328,6 +328,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, static int filter_frame(AVFilterLink *inlink, AVFrame *in) { + int err = 0; AVFilterContext *ctx = inlink->dst; TransContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -339,10 +340,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + err = AVERROR(ENOMEM); + goto fail; } - av_frame_copy_props(out, in); + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; if (in->sample_aspect_ratio.num == 0) { out->sample_aspect_ratio = in->sample_aspect_ratio; @@ -356,6 +360,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); av_frame_free(&in); return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; } #define OFFSET(x) offsetof(TransContext, x) From 58816f6927745d3512b26efcc7e5d88bee249e53 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Thu, 9 Dec 2021 17:36:51 +0800 Subject: [PATCH 440/894] avfilter: add a transpose_vulkan filter The following command is on how to apply transpose_vulkan filter: ffmpeg -init_hw_device vulkan -i input.264 -vf \ hwupload=extra_hw_frames=16,transpose_vulkan,hwdownload,format=yuv420p output.264 Signed-off-by: Wu Jianhua --- configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_transpose_vulkan.c | 316 ++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 libavfilter/vf_transpose_vulkan.c diff --git a/configure b/configure index 04f319b197..a7593ec2db 100755 --- a/configure +++ b/configure @@ -3718,6 +3718,7 @@ tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" tonemap_opencl_filter_deps="opencl const_nan" transpose_opencl_filter_deps="opencl" transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" +transpose_vulkan_filter_deps="vulkan spirv_compiler" unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" vaguedenoiser_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index c8082c4a2f..8744cc3c63 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -483,6 +483,7 @@ OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o OBJS-$(CONFIG_TRANSPOSE_NPP_FILTER) += vf_transpose_npp.o OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o opencl/transpose.o OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o +OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER) += vf_transpose_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_TRIM_FILTER) += trim.o OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index b1af2cbcc8..9e16b4e71e 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -462,6 +462,7 @@ extern const AVFilter ff_vf_transpose; extern const AVFilter ff_vf_transpose_npp; extern const AVFilter ff_vf_transpose_opencl; extern const AVFilter ff_vf_transpose_vaapi; +extern const AVFilter ff_vf_transpose_vulkan; extern const AVFilter ff_vf_trim; extern const AVFilter ff_vf_unpremultiply; extern const AVFilter ff_vf_unsharp; diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c new file mode 100644 index 0000000000..c9bae413c3 --- /dev/null +++ b/libavfilter/vf_transpose_vulkan.c @@ -0,0 +1,316 @@ +/* + * copyright (c) 2021 Wu Jianhua + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/random_seed.h" +#include "libavutil/opt.h" +#include "vulkan_filter.h" +#include "internal.h" + +#define CGS 32 + +typedef struct TransposeVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl; + + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo output_images[3]; + + int initialized; +} TransposeVulkanContext; + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err = 0; + FFVkSPIRVShader *shd; + TransposeVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + FFVulkanDescriptorSetBinding image_descs[] = { + { + .name = "input_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->input_images, + }, + { + .name = "output_images", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->output_images, + }, + }; + + image_descs[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!image_descs[0].sampler) + return AVERROR_EXTERNAL; + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + { + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); + if (!s->pl) + return AVERROR(ENOMEM); + + shd = ff_vk_init_shader(s->pl, "transpose_compute", image_descs[0].stages); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_images[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + GLSLF(2, vec4 res = texture(input_images[%i], pos.yx); ,i); + GLSLF(2, imageStore(output_images[%i], pos, res); ,i); + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(vkctx, shd, "main")); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); + } + + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + s->initialized = 1; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe) +{ + int err = 0; + VkCommandBuffer cmd_buf; + TransposeVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &s->vkctx.vkfn; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + AVVkFrame *in = (AVVkFrame *)inframe->data[0]; + AVVkFrame *out = (AVVkFrame *)outframe->data[0]; + + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); + + for (int i = 0; i < planes; i++) { + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], + input_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + output_formats[i], + ff_comp_identity_map)); + + s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + ff_vk_update_descriptor_set(vkctx, s->pl, 0); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = in->layout[i], + .newLayout = s->input_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = in->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, + .oldLayout = out->layout[i], + .newLayout = s->output_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = out->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + }; + + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers); + + in->layout[i] = barriers[0].newLayout; + in->access[i] = barriers[0].dstAccessMask; + + out->layout[i] = barriers[1].newLayout; + out->access[i] = barriers[1].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + s->vkctx.output_height, 1); + + ff_vk_add_exec_dep(vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + err = ff_vk_submit_exec_queue(vkctx, s->exec); + if (err) + return err; + + ff_vk_qf_rotate(&s->qf); + + return 0; + +fail: + ff_vk_discard_exec_deps(s->exec); + return err; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = inlink->dst; + TransposeVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) + RET(init_filter(ctx, in)); + + RET(process_frames(ctx, out, in)); + + RET(av_frame_copy_props(out, in)); + + if (in->sample_aspect_ratio.num) + out->sample_aspect_ratio = in->sample_aspect_ratio; + else { + out->sample_aspect_ratio.num = in->sample_aspect_ratio.den; + out->sample_aspect_ratio.den = in->sample_aspect_ratio.num; + } + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx) +{ + TransposeVulkanContext *s = avctx->priv; + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int config_props_output(AVFilterLink *outlink) +{ + int err = 0; + AVFilterContext *avctx = outlink->src; + TransposeVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + AVFilterLink *inlink = avctx->inputs[0]; + + vkctx->output_width = inlink->h; + vkctx->output_height = inlink->w; + + RET(ff_vk_filter_config_output(outlink)); + + outlink->w = inlink->h; + outlink->h = inlink->w; + + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 }, + inlink->sample_aspect_ratio); + else + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + + err = 0; + +fail: + return err; +} + +static const AVOption transpose_vulkan_options[] = { + { NULL } +}; + +AVFILTER_DEFINE_CLASS(transpose_vulkan); + +static const AVFilterPad transpose_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +static const AVFilterPad transpose_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &config_props_output, + } +}; + +const AVFilter ff_vf_transpose_vulkan = { + .name = "transpose_vulkan", + .description = NULL_IF_CONFIG_SMALL("Transpose Vulkan Filter"), + .priv_size = sizeof(TransposeVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &transpose_vulkan_uninit, + FILTER_INPUTS(transpose_vulkan_inputs), + FILTER_OUTPUTS(transpose_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &transpose_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From e050959103f375e6494937fa28ef2c4d2d15c9ef Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Tue, 7 Dec 2021 17:05:49 +0800 Subject: [PATCH 441/894] hwcontext_vaapi: Use PRIME_2 memory type for modifiers. This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++++++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; + // Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for + // surface imports. + int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { + VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; - VAStatus vas; + VAStatus vas = VA_STATUS_SUCCESS; + int use_prime2; uint32_t va_fourcc; - int err, i, j, k; - - unsigned long buffer_handle; - VASurfaceAttribExternalBuffers buffer_desc; - VASurfaceAttrib attrs[2] = { - { - .type = VASurfaceAttribMemoryType, - .flags = VA_SURFACE_ATTRIB_SETTABLE, - .value.type = VAGenericValueTypeInteger, - .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, - }, - { - .type = VASurfaceAttribExternalBufferDescriptor, - .flags = VA_SURFACE_ATTRIB_SETTABLE, - .value.type = VAGenericValueTypePointer, - .value.value.p = &buffer_desc, - } - }; + int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); - buffer_handle = desc->objects[0].fd; - buffer_desc.pixel_format = va_fourcc; - buffer_desc.width = src_fc->width; - buffer_desc.height = src_fc->height; - buffer_desc.data_size = desc->objects[0].size; - buffer_desc.buffers = &buffer_handle; - buffer_desc.num_buffers = 1; - buffer_desc.flags = 0; - - k = 0; - for (i = 0; i < desc->nb_layers; i++) { - for (j = 0; j < desc->layers[i].nb_planes; j++) { - buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; - buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; - ++k; + use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; + if (use_prime2) { + VADRMPRIMESurfaceDescriptor prime_desc; + VASurfaceAttrib prime_attrs[2] = { + { + .type = VASurfaceAttribMemoryType, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypeInteger, + .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + }, + { + .type = VASurfaceAttribExternalBufferDescriptor, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypePointer, + .value.value.p = &prime_desc, + } + }; + prime_desc.fourcc = va_fourcc; + prime_desc.width = src_fc->width; + prime_desc.height = src_fc->height; + prime_desc.num_objects = desc->nb_objects; + for (i = 0; i < desc->nb_objects; ++i) { + prime_desc.objects[i].fd = desc->objects[i].fd; + prime_desc.objects[i].size = desc->objects[i].size; + prime_desc.objects[i].drm_format_modifier = + desc->objects[i].format_modifier; } - } - buffer_desc.num_planes = k; - if (format_desc->chroma_planes_swapped && - buffer_desc.num_planes == 3) { - FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]); - FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]); + prime_desc.num_layers = desc->nb_layers; + for (i = 0; i < desc->nb_layers; ++i) { + prime_desc.layers[i].drm_format = desc->layers[i].format; + prime_desc.layers[i].num_planes = desc->layers[i].nb_planes; + for (j = 0; j < desc->layers[i].nb_planes; ++j) { + prime_desc.layers[i].object_index[j] = + desc->layers[i].planes[j].object_index; + prime_desc.layers[i].offset[j] = desc->layers[i].planes[j].offset; + prime_desc.layers[i].pitch[j] = desc->layers[i].planes[j].pitch; + } + + if (format_desc->chroma_planes_swapped && + desc->layers[i].nb_planes == 3) { + FFSWAP(uint32_t, prime_desc.layers[i].pitch[1], + prime_desc.layers[i].pitch[2]); + FFSWAP(uint32_t, prime_desc.layers[i].offset[1], + prime_desc.layers[i].offset[2]); + } + } + + /* + * We can query for PRIME_2 support with vaQuerySurfaceAttributes, but that + * that needs the config_id which we don't have here . Both Intel and + * Gallium seem to do the correct error checks, so lets just try the + * PRIME_2 import first. + */ + vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, + src->width, src->height, &surface_id, 1, + prime_attrs, FF_ARRAY_ELEMS(prime_attrs)); + if (vas != VA_STATUS_SUCCESS) + src_vafc->prime_2_import_unsupported = 1; } - vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, - src->width, src->height, - &surface_id, 1, - attrs, FF_ARRAY_ELEMS(attrs)); + if (!use_prime2 || vas != VA_STATUS_SUCCESS) { + int k; + unsigned long buffer_handle; + VASurfaceAttribExternalBuffers buffer_desc; + VASurfaceAttrib buffer_attrs[2] = { + { + .type = VASurfaceAttribMemoryType, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypeInteger, + .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, + }, + { + .type = VASurfaceAttribExternalBufferDescriptor, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypePointer, + .value.value.p = &buffer_desc, + } + }; + + buffer_handle = desc->objects[0].fd; + buffer_desc.pixel_format = va_fourcc; + buffer_desc.width = src_fc->width; + buffer_desc.height = src_fc->height; + buffer_desc.data_size = desc->objects[0].size; + buffer_desc.buffers = &buffer_handle; + buffer_desc.num_buffers = 1; + buffer_desc.flags = 0; + + k = 0; + for (i = 0; i < desc->nb_layers; i++) { + for (j = 0; j < desc->layers[i].nb_planes; j++) { + buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; + buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; + ++k; + } + } + buffer_desc.num_planes = k; + + if (format_desc->chroma_planes_swapped && + buffer_desc.num_planes == 3) { + FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]); + FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]); + } + + vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, + src->width, src->height, + &surface_id, 1, + buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs)); + } if (vas != VA_STATUS_SUCCESS) { av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM " "object: %d (%s).\n", vas, vaErrorStr(vas)); From f3c9847c2754b7a43eb721c95e356a53085c2491 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Tue, 7 Dec 2021 17:05:50 +0800 Subject: [PATCH 442/894] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), + DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) From bd6ef73399f3f2fcd59ae2ff358954bb536540f2 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Tue, 7 Dec 2021 17:05:51 +0800 Subject: [PATCH 443/894] hwcontext_vulkan: add support for allocating all planes in a single allocation VAAPI on Intel can import external frame, but the planes of the external frames should be in the same drm object. A new option "contiguous_planes" is added to device. This flag tells device to allocate places in one memory. When device is derived from vaapi this flag will be enabled. A new flag frame_flag is also added to AVVulkanFramesContext. User can use this flag to force enable or disable this behaviour. A new variable "offset "is added to AVVKFrame. It describe describe the offset from the memory currently bound to the VkImage. Signed-off-by: Wenbin Chen Further-modifications-by: Lynne --- libavutil/hwcontext_vulkan.c | 76 +++++++++++++++++++++++++++++++++++- libavutil/hwcontext_vulkan.h | 31 ++++++++++++++- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a0437c9661..ffd4f0e643 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -103,8 +103,14 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; + /* Option to allocate all image planes in a single allocation */ + int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; + + /* Intel */ + int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -1374,6 +1380,12 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); + opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); + if (opt_d) + p->contiguous_planes = strtol(opt_d->value, NULL, 10); + else + p->contiguous_planes = -1; + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1424,6 +1436,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->hprops.minImportedHostPointerAlignment); p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); + p->dev_is_intel = (p->props.properties.vendorID == 0x8086); vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { @@ -1742,9 +1755,14 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; + VkMemoryRequirements cont_memory_requirements = { 0 }; + int cont_mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; + int cont_mem_size = 0; + AVVulkanDeviceContext *hwctx = ctx->hwctx; for (int i = 0; i < planes; i++) { @@ -1771,6 +1789,27 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { + if (ded_req.requiresDedicatedAllocation) { + av_log(hwfc, AV_LOG_ERROR, "Cannot allocate all planes in a single allocation, " + "device requires dedicated image allocation!\n"); + return AVERROR(EINVAL); + } else if (!i) { + cont_memory_requirements = req.memoryRequirements; + } else if (cont_memory_requirements.memoryTypeBits != + req.memoryRequirements.memoryTypeBits) { + av_log(hwfc, AV_LOG_ERROR, "The memory requirements differ between plane 0 " + "and %i, cannot allocate in a single region!\n", + i); + return AVERROR(EINVAL); + } + + cont_mem_size_list[i] = FFALIGN(req.memoryRequirements.size, + req.memoryRequirements.alignment); + cont_mem_size += cont_mem_size_list[i]; + continue; + } + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1792,6 +1831,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { + cont_memory_requirements.size = cont_mem_size; + + /* Allocate memory */ + if ((err = alloc_mem(ctx, &cont_memory_requirements, + f->tiling == VK_IMAGE_TILING_LINEAR ? + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + (void *)(((uint8_t *)alloc_pnext)), + &f->flags, &f->mem[0]))) + return err; + + f->size[0] = cont_memory_requirements.size; + + for (int i = 0; i < planes; i++) { + bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + bind_info[i].image = f->img[i]; + bind_info[i].memory = f->mem[0]; + bind_info[i].memoryOffset = !i ? 0 : cont_mem_size_list[i - 1]; + f->offset[i] = bind_info[i].memoryOffset; + } + } + /* Bind the allocated memory to the images */ ret = vk->BindImageMemory2(hwctx->act_dev, planes, bind_info); if (ret != VK_SUCCESS) { @@ -2154,6 +2216,12 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) if (!hwctx->usage) hwctx->usage = FF_VK_DEFAULT_USAGE_FLAGS; + if (!(hwctx->flags & AV_VK_FRAME_FLAG_NONE)) { + if (p->contiguous_planes == 1 || + ((p->contiguous_planes == -1) && p->dev_is_intel)) + hwctx->flags |= AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY; + } + err = create_exec_ctx(hwfc, &fp->conv_ctx, dev_hwctx->queue_family_comp_index, dev_hwctx->nb_comp_queues); @@ -3074,6 +3142,7 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkImageDrmFormatModifierPropertiesEXT drm_mod = { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, @@ -3142,8 +3211,11 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, continue; vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); - drm_desc->layers[i].planes[0].offset = layout.offset; - drm_desc->layers[i].planes[0].pitch = layout.rowPitch; + drm_desc->layers[i].planes[0].offset = layout.offset; + drm_desc->layers[i].planes[0].pitch = layout.rowPitch; + + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) + drm_desc->layers[i].planes[0].offset += f->offset[i]; } dst->width = src->width; diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index fdf2a60156..ed59fe9f0a 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -137,6 +137,20 @@ typedef struct AVVulkanDeviceContext { int nb_decode_queues; } AVVulkanDeviceContext; +/** + * Defines the behaviour of frame allocation. + */ +typedef enum AVVkFrameFlags { + /* Unless this flag is set, autodetected flags will be OR'd based on the + * device and tiling during av_hwframe_ctx_init(). */ + AV_VK_FRAME_FLAG_NONE = (1ULL << 0), + + /* Image planes will be allocated in a single VkDeviceMemory, rather + * than as per-plane VkDeviceMemory allocations. Required for exporting + * to VAAPI on Intel devices. */ + AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY = (1ULL << 1), +} AVVkFrameFlags; + /** * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options */ @@ -165,6 +179,13 @@ typedef struct AVVulkanFramesContext { * extensions are present in enabled_dev_extensions. */ void *alloc_pnext[AV_NUM_DATA_POINTERS]; + + /** + * A combination of AVVkFrameFlags. Unless AV_VK_FRAME_FLAG_NONE is set, + * autodetected flags will be OR'd based on the device and tiling during + * av_hwframe_ctx_init(). + */ + AVVkFrameFlags flags; } AVVulkanFramesContext; /* @@ -192,8 +213,9 @@ typedef struct AVVkFrame { VkImageTiling tiling; /** - * Memory backing the images. Could be less than the amount of images - * if importing from a DRM or VAAPI frame. + * Memory backing the images. Could be less than the amount of planes, + * in which case the offset value will indicate the binding offset of + * each plane in the memory. */ VkDeviceMemory mem[AV_NUM_DATA_POINTERS]; size_t size[AV_NUM_DATA_POINTERS]; @@ -230,6 +252,11 @@ typedef struct AVVkFrame { * Internal data. */ struct AVVkFrameInternal *internal; + + /** + * Describes the binding offset of each plane to the VkDeviceMemory. + */ + ptrdiff_t offset[AV_NUM_DATA_POINTERS]; } AVVkFrame; /** From 0d524b170ec4bf762e11c49743d813de650d409a Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Tue, 7 Dec 2021 17:05:52 +0800 Subject: [PATCH 444/894] hwcontext_vulkan: add support for mapping frames with planes in a single VkDeviceMemory Add support to map vulkan frames to software frames when using contiguous_planes flag. Signed-off-by: Wenbin Chen Further-modifications-by: Lynne --- libavutil/hwcontext_vulkan.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ffd4f0e643..728f800bb2 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2332,9 +2332,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; - int err, mapped_mem_count = 0; + int err, mapped_mem_count = 0, mem_planes = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -2361,7 +2362,8 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; - for (int i = 0; i < planes; i++) { + mem_planes = hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY ? 1 : planes; + for (int i = 0; i < mem_planes; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2373,6 +2375,11 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, mapped_mem_count++; } + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { + for (int i = 0; i < planes; i++) + dst->data[i] = dst->data[0] + f->offset[i]; + } + /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && !(f->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { From 83fe28221e92921f74d99ed15c258a3c79f4441d Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Tue, 7 Dec 2021 17:05:53 +0800 Subject: [PATCH 445/894] hwcontext_vulkan: support creating DRM-tiled images and autodetecting modifiers When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen Further-modifications-by: Lynne --- libavutil/hwcontext_vulkan.c | 163 +++++++++++++++++++++++++++++++++-- libavutil/hwcontext_vulkan.h | 11 ++- 2 files changed, 165 insertions(+), 9 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 728f800bb2..507c4f4454 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -120,6 +120,9 @@ typedef struct VulkanFramesPriv { /* Image transfers */ VulkanExecCtx upload_ctx; VulkanExecCtx download_ctx; + + /* Modifier info list to free at uninit */ + VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -240,6 +243,31 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static const void *vk_find_struct(const void *chain, VkStructureType stype) +{ + const VkBaseInStructure *in = chain; + while (in) { + if (in->sType == stype) + return in; + + in = in->pNext; + } + + return NULL; +} + +static void vk_link_struct(void *chain, void *in) +{ + VkBaseOutStructure *out = chain; + if (!in) + return; + + while (out->pNext) + out = out->pNext; + + out->pNext = in; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { @@ -2099,6 +2127,13 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; + + const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info = + vk_find_struct(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); + int has_mods = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info; + int nb_mods; + VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -2106,9 +2141,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; + VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, + .pNext = NULL, + .pQueueFamilyIndices = p->qfs, + .queueFamilyIndexCount = p->num_qfs, + .sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, + }; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, + .pNext = has_mods ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -2120,11 +2164,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; - ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); - if (ret == VK_SUCCESS) { - *iexp |= exp; - *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; + nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1; + for (int i = 0; i < nb_mods; i++) { + if (has_mods) + phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[i]; + + ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, + &pinfo, &props); + + if (ret == VK_SUCCESS) { + *iexp |= exp; + *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; + } } } @@ -2195,6 +2246,12 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; + if (fp->modifier_info) { + if (fp->modifier_info->pDrmFormatModifiers) + av_freep(&fp->modifier_info->pDrmFormatModifiers); + av_freep(&fp->modifier_info); + } + free_exec_ctx(hwfc, &fp->conv_ctx); free_exec_ctx(hwfc, &fp->upload_ctx); free_exec_ctx(hwfc, &fp->download_ctx); @@ -2208,10 +2265,14 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + const VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; + const int has_modifiers = !!(p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS); - /* Default pool flags */ - hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ? - VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; + /* Default tiling flags */ + hwctx->tiling = hwctx->tiling ? hwctx->tiling : + has_modifiers ? VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : + p->use_linear_images ? VK_IMAGE_TILING_LINEAR : + VK_IMAGE_TILING_OPTIMAL; if (!hwctx->usage) hwctx->usage = FF_VK_DEFAULT_USAGE_FLAGS; @@ -2222,6 +2283,92 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) hwctx->flags |= AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY; } + modifier_info = vk_find_struct(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); + + /* Get the supported modifiers if the user has not given any. */ + if (has_modifiers && !modifier_info) { + const VkFormat *fmt = av_vkfmt_from_pixfmt(hwfc->sw_format); + VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; + FFVulkanFunctions *vk = &p->vkfn; + VkDrmFormatModifierPropertiesEXT *mod_props; + uint64_t *modifiers; + int modifier_count = 0; + + VkDrmFormatModifierPropertiesListEXT mod_props_list = { + .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, + .pNext = NULL, + .drmFormatModifierCount = 0, + .pDrmFormatModifierProperties = NULL, + }; + VkFormatProperties2 prop = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + .pNext = &mod_props_list, + }; + + /* Get all supported modifiers */ + vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop); + + if (!mod_props_list.drmFormatModifierCount) { + av_log(hwfc, AV_LOG_ERROR, "There are no supported modifiers for the given sw_format\n"); + return AVERROR(EINVAL); + } + + /* Createa structure to hold the modifier list info */ + modifier_info = av_mallocz(sizeof(*modifier_info)); + if (!modifier_info) + return AVERROR(ENOMEM); + + modifier_info->pNext = NULL; + modifier_info->sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT; + + /* Add structure to the image creation pNext chain */ + if (!hwctx->create_pnext) + hwctx->create_pnext = modifier_info; + else + vk_link_struct(hwctx->create_pnext, (void *)modifier_info); + + /* Backup the allocated struct to be freed later */ + fp->modifier_info = modifier_info; + + /* Allocate list of modifiers */ + modifiers = av_mallocz(mod_props_list.drmFormatModifierCount * + sizeof(*modifiers)); + if (!modifiers) + return AVERROR(ENOMEM); + + modifier_info->pDrmFormatModifiers = modifiers; + + /* Allocate a temporary list to hold all modifiers supported */ + mod_props = av_mallocz(mod_props_list.drmFormatModifierCount * + sizeof(*mod_props)); + if (!mod_props) + return AVERROR(ENOMEM); + + mod_props_list.pDrmFormatModifierProperties = mod_props; + + /* Finally get all modifiers from the device */ + vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop); + + /* Reject any modifiers that don't match our requirements */ + for (int i = 0; i < mod_props_list.drmFormatModifierCount; i++) { + if (!(mod_props[i].drmFormatModifierTilingFeatures & hwctx->usage)) + continue; + + modifiers[modifier_count++] = mod_props[i].drmFormatModifier; + } + + if (!modifier_count) { + av_log(hwfc, AV_LOG_ERROR, "None of the given modifiers supports" + " the usage flags!\n"); + av_freep(&mod_props); + return AVERROR(EINVAL); + } + + modifier_info->drmFormatModifierCount = modifier_count; + av_freep(&mod_props); + } + err = create_exec_ctx(hwfc, &fp->conv_ctx, dev_hwctx->queue_family_comp_index, dev_hwctx->nb_comp_queues); diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index ed59fe9f0a..8de79f5f33 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -156,7 +156,10 @@ typedef enum AVVkFrameFlags { */ typedef struct AVVulkanFramesContext { /** - * Controls the tiling of allocated frames. + * Controls the tiling of allocated frames. If left as optimal tiling, + * then during av_hwframe_ctx_init() will decide based on whether the device + * supports DRM modifiers, or if the linear_images flag is set, otherwise + * will allocate optimally-tiled images. */ VkImageTiling tiling; @@ -168,6 +171,12 @@ typedef struct AVVulkanFramesContext { /** * Extension data for image creation. + * If VkImageDrmFormatModifierListCreateInfoEXT is present in the chain, + * and the device supports DRM modifiers, then images will be allocated + * with the specific requested DRM modifiers. + * Additional structures may be added at av_hwframe_ctx_init() time, + * which will be freed automatically on uninit(), so users need only free + * any structures they've allocated themselves. */ void *create_pnext; From 0747768728b9bc67bc2883425fa7a315457708da Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 10 Dec 2021 16:29:03 +0100 Subject: [PATCH 446/894] hwcontext_vulkan: stricter semaphore number requirements Always require one semaphore per sw_format plane. This is what the implementation uses and relies upon throughout. This was a leftover from an earlier revision that was never needed. --- libavutil/hwcontext_vulkan.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 8de79f5f33..df86c85b3c 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -241,12 +241,10 @@ typedef struct AVVkFrame { VkImageLayout layout[AV_NUM_DATA_POINTERS]; /** - * Synchronization timeline semaphores. Must not be freed manually. - * Must be waited on at every submission using the value in sem_value, - * and must be signalled at every submission, using an incremented value. - * - * Could be less than the amount of images: either one per VkDeviceMemory - * or one for the entire frame. All others will be set to VK_NULL_HANDLE. + * Synchronization timeline semaphores, one for each sw_format plane. + * Must not be freed manually. Must be waited on at every submission using + * the value in sem_value, and must be signalled at every submission, + * using an incremented value. */ VkSemaphore sem[AV_NUM_DATA_POINTERS]; From f45cbb775e47c9991cb518841b2c094e1046dff9 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 10 Dec 2021 16:34:52 +0100 Subject: [PATCH 447/894] lavu: bump minor version and add doc/APIchanges entry for Vulkan changes --- doc/APIchanges | 3 +++ libavutil/version.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2914ad6734..2d41d67818 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-11-10 - xxxxxxxxxx - lavu 57.11.100 - hwcontext_vulkan.h + Add AVVkFrame.offset and AVVulkanFramesContext.flags. + 2021-11-xx - xxxxxxxxxx - lavfi 8.19.100 - avfilter.h Add AVFILTER_FLAG_METADATA_ONLY. diff --git a/libavutil/version.h b/libavutil/version.h index 017fc277a6..0e7b36865a 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,8 +79,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 10 -#define LIBAVUTIL_VERSION_MICRO 101 +#define LIBAVUTIL_VERSION_MINOR 11 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From 0c1d47a6b39ba19c0883e6322ca509eb8e73e875 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 10 Dec 2021 17:16:49 +0100 Subject: [PATCH 448/894] hwcontext_vulkan: wait on semaphores when exporting to DRM There is no synchronization method for DRM yet. --- libavutil/hwcontext_vulkan.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 507c4f4454..83a7527198 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -3301,6 +3301,11 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, VkImageDrmFormatModifierPropertiesEXT drm_mod = { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, }; + VkSemaphoreWaitInfo wait_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .flags = 0x0, + .semaphoreCount = planes, + }; AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc)); if (!drm_desc) @@ -3310,6 +3315,12 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, if (err < 0) goto end; + /* Wait for the operation to finish so we can cleanly export it. */ + wait_info.pSemaphores = f->sem; + wait_info.pValues = f->sem_value; + + vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &vulkan_unmap_to_drm, drm_desc); if (err < 0) goto end; From f106c7228503241d044fb404d1012047d6452f74 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Sat, 11 Dec 2021 03:05:00 +0800 Subject: [PATCH 449/894] avfilter/vf_transpose_vulkan: add clock and cclock option The following command is on how to apply cclock option: ffmpeg -init_hw_device vulkan -i input.264 -vf \ hwupload=extra_hw_frames=16,transpose_vulkan=dir=cclock,hwdownload,format=yuv420p \ output.264 The following command is on how to apply clock_flip option: ffmpeg -init_hw_device vulkan -i input.264 -vf \ hwupload=extra_hw_frames=16,transpose_vulkan=dir=clock_flip,hwdownload,format=yuv420p \ output.264 The following command is on how to apply clock option: ffmpeg -init_hw_device vulkan -i input.264 -vf \ hwupload=extra_hw_frames=16,transpose_vulkan=dir=clock,hwdownload,format=yuv420p \ output.264 Signed-off-by: Wu Jianhua --- libavfilter/vf_transpose_vulkan.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c index c9bae413c3..eceb9b9011 100644 --- a/libavfilter/vf_transpose_vulkan.c +++ b/libavfilter/vf_transpose_vulkan.c @@ -21,6 +21,7 @@ #include "libavutil/opt.h" #include "vulkan_filter.h" #include "internal.h" +#include "transpose.h" #define CGS 32 @@ -33,6 +34,7 @@ typedef struct TransposeVulkanContext { VkDescriptorImageInfo input_images[3]; VkDescriptorImageInfo output_images[3]; + int dir; int initialized; } TransposeVulkanContext; @@ -86,13 +88,20 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) GLSLC(0, void main() ); GLSLC(0, { ); GLSLC(1, ivec2 size; ); - GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); for (int i = 0; i < planes; i++) { GLSLC(0, ); - GLSLF(1, size = imageSize(output_images[%i]); ,i); + GLSLF(1, size = imageSize(output_images[%i]); ,i); GLSLC(1, if (IS_WITHIN(pos, size)) { ); - GLSLF(2, vec4 res = texture(input_images[%i], pos.yx); ,i); - GLSLF(2, imageStore(output_images[%i], pos, res); ,i); + if (s->dir == TRANSPOSE_CCLOCK) + GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.y - pos.y, pos.x)); ,i); + else if (s->dir == TRANSPOSE_CLOCK_FLIP || s->dir == TRANSPOSE_CLOCK) { + GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.yx - pos.yx)); ,i); + if (s->dir == TRANSPOSE_CLOCK) + GLSLC(2, pos = ivec2(pos.x, size.y - pos.y); ); + } else + GLSLF(2, vec4 res = texture(input_images[%i], pos.yx); ,i); + GLSLF(2, imageStore(output_images[%i], pos, res); ,i); GLSLC(1, } ); } GLSLC(0, } ); @@ -279,7 +288,15 @@ fail: return err; } +#define OFFSET(x) offsetof(TransposeVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + static const AVOption transpose_vulkan_options[] = { + { "dir", "set transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 7, FLAGS, "dir" }, + { "cclock_flip", "rotate counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, + { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "dir" }, + { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "dir" }, + { "clock_flip", "rotate clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, { NULL } }; From f176669a374c16d45bb0b8464de3b8a73f791e2d Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Sat, 11 Dec 2021 03:05:03 +0800 Subject: [PATCH 450/894] avfilter/vf_transpose_vulkan: simplify config_props_output function It's no need to assign outlink here, which has been done in ff_vk_filter_config_output already. Signed-off-by: Wu Jianhua --- libavfilter/vf_transpose_vulkan.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c index eceb9b9011..ce83cf0fd7 100644 --- a/libavfilter/vf_transpose_vulkan.c +++ b/libavfilter/vf_transpose_vulkan.c @@ -262,7 +262,6 @@ static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx) static int config_props_output(AVFilterLink *outlink) { - int err = 0; AVFilterContext *avctx = outlink->src; TransposeVulkanContext *s = avctx->priv; FFVulkanContext *vkctx = &s->vkctx; @@ -271,21 +270,13 @@ static int config_props_output(AVFilterLink *outlink) vkctx->output_width = inlink->h; vkctx->output_height = inlink->w; - RET(ff_vk_filter_config_output(outlink)); - - outlink->w = inlink->h; - outlink->h = inlink->w; - if (inlink->sample_aspect_ratio.num) outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 }, inlink->sample_aspect_ratio); else outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - err = 0; - -fail: - return err; + return ff_vk_filter_config_output(outlink); } #define OFFSET(x) offsetof(TransposeVulkanContext, x) From cd693c9ec8a83eca7c5e79c454a451c7936749c5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 8 Dec 2021 21:08:58 +0100 Subject: [PATCH 451/894] avcodec/movtextdec: Switch to smaller type The base size of a box refers to the size the box has in a file, not in memory; so size_t is not their natural type. Therefore use a plain unsigned which is smaller on 64bit systems and still big enough to represent any conceivable base size. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index b0c54bf1d0..8dd571d64c 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -111,7 +111,7 @@ typedef struct { typedef struct { uint32_t type; - size_t base_size; + unsigned base_size; int (*decode)(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt); } Box; From b9f5a26a39efc0e49e2296306efde572630b1796 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 8 Dec 2021 15:04:25 +0100 Subject: [PATCH 452/894] avcodec/movtextdec: Improve size check Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 8dd571d64c..5083308d58 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -537,8 +537,8 @@ static int mov_text_decode_frame(AVCodecContext *avctx, m->size_var = 8; //size_var is equal to 8 or 16 depending on the size of box - if (tsmb_size == 0) { - av_log(avctx, AV_LOG_ERROR, "tsmb_size is 0\n"); + if (tsmb_size < m->size_var) { + av_log(avctx, AV_LOG_ERROR, "tsmb_size invalid\n"); return AVERROR_INVALIDDATA; } From efd7b35d0688e7ffb0300288b15870b2070ddb69 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 8 Dec 2021 15:31:05 +0100 Subject: [PATCH 453/894] avcodec/movtextdec: Use const where appropriate Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 5083308d58..001df6a5a1 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -481,8 +481,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, MovTextContext *m = avctx->priv_data; int ret; AVBPrint buf; - char *ptr = avpkt->data; - char *end; + const char *ptr = avpkt->data, *end; int text_length, tsmb_type, ret_tsmb; uint64_t tsmb_size; const uint8_t *tsmb; From e1044e55e45980b45d7181549fc97dbc954eb4e9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 8 Dec 2021 16:03:03 +0100 Subject: [PATCH 454/894] avcodec/movtextdec: Redo TextSampleModifierBox size checks The current checks just check whether the boxes fit into the remaining size of the packet instead of whether they actually fit into the box size. This has been changed; part of this change is to pass the size of the box (minus the box header) as parameter instead of a pointer to the AVPacket by which the box parsing function is supposed to recalculate whether enough data is available. Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 001df6a5a1..967c0adf7f 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -103,7 +103,6 @@ typedef struct { uint8_t box_flags; uint16_t style_entries, ftab_entries; uint64_t tracksize; - int size_var; int readorder; int frame_width; int frame_height; @@ -112,7 +111,7 @@ typedef struct { typedef struct { uint32_t type; unsigned base_size; - int (*decode)(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt); + int (*decode)(const uint8_t *tsmb, MovTextContext *m, uint64_t size); } Box; static void mov_text_cleanup(MovTextContext *m) @@ -241,14 +240,14 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) return 0; } -static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { m->box_flags |= TWRP_BOX; m->w.wrap_flag = bytestream_get_byte(&tsmb); return 0; } -static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { m->box_flags |= HLIT_BOX; m->h.hlit_start = bytestream_get_be16(&tsmb); @@ -256,7 +255,7 @@ static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a return 0; } -static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { m->box_flags |= HCLR_BOX; bytestream_get_buffer(&tsmb, m->c.hlit_color, 4); @@ -271,14 +270,14 @@ static int styles_equivalent(const StyleBox *a, const StyleBox *b) #undef CMP } -static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_styl(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { int i; int style_entries = bytestream_get_be16(&tsmb); StyleBox *tmp; // A single style record is of length 12 bytes. - if (m->tracksize + m->size_var + 2 + style_entries * 12 > avpkt->size) + if (2 + style_entries * 12 > size) return -1; tmp = av_realloc_array(m->s, style_entries, sizeof(*m->s)); @@ -519,6 +518,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (text_length + 2 != avpkt->size) { while (m->tracksize + 8 <= avpkt->size) { + int size_var; // A box is a minimum of 8 bytes. tsmb = ptr + m->tracksize - 2; tsmb_size = AV_RB32(tsmb); @@ -531,12 +531,12 @@ static int mov_text_decode_frame(AVCodecContext *avctx, break; tsmb_size = AV_RB64(tsmb); tsmb += 8; - m->size_var = 16; + size_var = 16; } else - m->size_var = 8; + size_var = 8; //size_var is equal to 8 or 16 depending on the size of box - if (tsmb_size < m->size_var) { + if (tsmb_size < size_var) { av_log(avctx, AV_LOG_ERROR, "tsmb_size invalid\n"); return AVERROR_INVALIDDATA; } @@ -544,16 +544,18 @@ static int mov_text_decode_frame(AVCodecContext *avctx, if (tsmb_size > avpkt->size - m->tracksize) break; + m->tracksize += tsmb_size; + tsmb_size -= size_var; + for (i = 0; i < box_count; i++) { if (tsmb_type == box_types[i].type) { - if (m->tracksize + m->size_var + box_types[i].base_size > avpkt->size) + if (tsmb_size < box_types[i].base_size) break; - ret_tsmb = box_types[i].decode(tsmb, m, avpkt); + ret_tsmb = box_types[i].decode(tsmb, m, tsmb_size); if (ret_tsmb == -1) break; } } - m->tracksize = m->tracksize + tsmb_size; } text_to_ass(&buf, ptr, end, avctx); mov_text_cleanup(m); From bbc866c9c9e3674cb49eceba7ed41f92d8ff7f61 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 8 Dec 2021 17:28:29 +0100 Subject: [PATCH 455/894] avcodec/movtextdec: Switch to pointer comparisons and bytestream API Improves readability and avoids a redundant index variable that was mistakenly called "tracksize". Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 967c0adf7f..63709eb54b 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -102,7 +102,6 @@ typedef struct { MovTextDefault d; uint8_t box_flags; uint16_t style_entries, ftab_entries; - uint64_t tracksize; int readorder; int frame_width; int frame_height; @@ -481,9 +480,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, int ret; AVBPrint buf; const char *ptr = avpkt->data, *end; - int text_length, tsmb_type, ret_tsmb; - uint64_t tsmb_size; - const uint8_t *tsmb; + int text_length; size_t i; if (!ptr || avpkt->size < 2) @@ -510,27 +507,23 @@ static int mov_text_decode_frame(AVCodecContext *avctx, mov_text_cleanup(m); - tsmb_size = 0; - m->tracksize = 2 + text_length; m->style_entries = 0; m->box_flags = 0; // Note that the spec recommends lines be no longer than 2048 characters. av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - if (text_length + 2 != avpkt->size) { - while (m->tracksize + 8 <= avpkt->size) { - int size_var; - // A box is a minimum of 8 bytes. - tsmb = ptr + m->tracksize - 2; - tsmb_size = AV_RB32(tsmb); - tsmb += 4; - tsmb_type = AV_RB32(tsmb); - tsmb += 4; + if (text_length + 2 < avpkt->size) { + const uint8_t *tsmb = end; + const uint8_t *const tsmb_end = avpkt->data + avpkt->size; + // A box is a minimum of 8 bytes. + while (tsmb_end - tsmb >= 8) { + uint64_t tsmb_size = bytestream_get_be32(&tsmb); + uint32_t tsmb_type = bytestream_get_be32(&tsmb); + int size_var, ret_tsmb; if (tsmb_size == 1) { - if (m->tracksize + 16 > avpkt->size) + if (tsmb_end - tsmb < 8) break; - tsmb_size = AV_RB64(tsmb); - tsmb += 8; + tsmb_size = bytestream_get_be64(&tsmb); size_var = 16; } else size_var = 8; @@ -540,13 +533,11 @@ static int mov_text_decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "tsmb_size invalid\n"); return AVERROR_INVALIDDATA; } - - if (tsmb_size > avpkt->size - m->tracksize) - break; - - m->tracksize += tsmb_size; tsmb_size -= size_var; + if (tsmb_end - tsmb < tsmb_size) + break; + for (i = 0; i < box_count; i++) { if (tsmb_type == box_types[i].type) { if (tsmb_size < box_types[i].base_size) @@ -556,6 +547,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, break; } } + tsmb += tsmb_size; } text_to_ass(&buf, ptr, end, avctx); mov_text_cleanup(m); From 41b077762cda61a6975dabee9f58444815794619 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 8 Dec 2021 18:03:56 +0100 Subject: [PATCH 456/894] avcodec/movtextdec: Fix wrong error code Reviewed-by: Philip Langdale Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 63709eb54b..825632ca9b 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -294,7 +294,7 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, uint64_t size) if (style->end < style->start || (i && style->start < m->s[i - 1].end)) { mov_text_cleanup(m); - return AVERROR(ENOMEM); + return AVERROR_INVALIDDATA; } if (style->start == style->end) { /* Skip this style as it applies to no character */ From 34aee50a7f5a4b36f9f7daf827422d345c7868ed Mon Sep 17 00:00:00 2001 From: Charlie Monroe Date: Fri, 10 Dec 2021 11:20:18 +0100 Subject: [PATCH 457/894] avcodec/movtextenc: Check for existence of font name before using it Fixes crashes if the font name is NULL (which it is if a \fn tag is not followed by a font name). Signed-off-by: Charlie Monroe Signed-off-by: Andreas Rheinhardt --- libavcodec/movtextenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 5869942ec0..221cd76fea 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -494,8 +494,10 @@ static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id) static uint16_t find_font_id(MovTextContext *s, const char *name) { - int i; - for (i = 0; i < s->font_count; i++) { + if (!name) + return 1; + + for (int i = 0; i < s->font_count; i++) { if (!strcmp(name, s->fonts[i])) return i + 1; } From 722d28db129b2e52d19c1a5051ea4ab0a9b84062 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 30 Nov 2021 00:50:16 +0100 Subject: [PATCH 458/894] avformat/file: use proper return value in file_close Signed-off-by: Marton Balint --- libavformat/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/file.c b/libavformat/file.c index 9c23f680cd..7001750c80 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -266,7 +266,8 @@ static int64_t file_seek(URLContext *h, int64_t pos, int whence) static int file_close(URLContext *h) { FileContext *c = h->priv_data; - return close(c->fd); + int ret = close(c->fd); + return (ret == -1) ? AVERROR(errno) : 0; } static int file_open_dir(URLContext *h) From 8a40cfa4dab461643f4f93f3340c897d708ea221 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 30 Nov 2021 00:59:14 +0100 Subject: [PATCH 459/894] avformat/aviobuf: return stored AVIO context error on avio_close Otherwise IO errors at avio_flush() before closing may be lost. Signed-off-by: Marton Balint --- libavformat/aviobuf.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 14688a2262..969c127b23 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -1231,6 +1231,7 @@ int avio_close(AVIOContext *s) { FFIOContext *const ctx = ffiocontext(s); URLContext *h; + int ret, error; if (!s) return 0; @@ -1249,9 +1250,14 @@ int avio_close(AVIOContext *s) ctx->bytes_read, ctx->seek_count); av_opt_free(s); + error = s->error; avio_context_free(&s); - return ffurl_close(h); + ret = ffurl_close(h); + if (ret < 0) + return ret; + + return error; } int avio_closep(AVIOContext **s) From 8d66a07d657ba7ed8c5e95345d4eec770b55e438 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 30 Nov 2021 01:18:14 +0100 Subject: [PATCH 460/894] fftools/ffmpeg: close output files before cleanup This allows us to check the return value of avio_closep(). Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0f1834cdbe..bdeff9a12e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4699,7 +4699,7 @@ static int transcode(void) term_exit(); - /* write the trailer if needed and close file */ + /* write the trailer if needed */ for (i = 0; i < nb_output_files; i++) { os = output_files[i]->ctx; if (!output_files[i]->header_written) { @@ -4719,6 +4719,18 @@ static int transcode(void) /* dump report by using the first video and audio streams */ print_report(1, timer_start, av_gettime_relative()); + /* close the output files */ + for (i = 0; i < nb_output_files; i++) { + os = output_files[i]->ctx; + if (os && os->oformat && !(os->oformat->flags & AVFMT_NOFILE)) { + if ((ret = avio_closep(&os->pb)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Error closing file %s: %s\n", os->url, av_err2str(ret)); + if (exit_on_error) + exit_program(1); + } + } + } + /* close each encoder */ for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; From 64834bb86a133400970d203656a30ae6a3d2832f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 30 Nov 2021 00:38:30 +0100 Subject: [PATCH 461/894] avformat: introduce AVFormatContext io_close2 which returns an int Otherwise there is no way to detect an error returned by avio_close() because ff_format_io_close cannot get the return value. Checking the return value of the close function is important in order to check if all data was successfully written and the underlying close() operation was successful. It can also be useful even for read mode because it can return any pending AVIOContext error, so the user don't have to manually check AVIOContext->error. In order to still support if the user overrides io_close, the generic code only uses io_close2 if io_close is either NULL or the default io_close callback. Signed-off-by: Marton Balint --- doc/APIchanges | 3 +++ libavformat/avformat.h | 13 +++++++++++++ libavformat/dashenc.c | 1 + libavformat/fifo.c | 1 + libavformat/hlsenc.c | 1 + libavformat/internal.h | 10 +++++++++- libavformat/options.c | 7 ++++--- libavformat/segment.c | 1 + libavformat/tee.c | 1 + libavformat/utils.c | 17 ++++++++++++++--- libavformat/version.h | 4 ++-- 11 files changed, 50 insertions(+), 9 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2d41d67818..17aa664ca3 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-xx - xxxxxxxxxx - lavf 59.10.100 - avformat.h + Add AVFormatContext io_close2 which returns an int + 2021-11-10 - xxxxxxxxxx - lavu 57.11.100 - hwcontext_vulkan.h Add AVVkFrame.offset and AVVulkanFramesContext.flags. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 75699f3a32..70b36d7682 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1786,6 +1786,19 @@ typedef struct AVFormatContext { * - decoding: set by user */ int max_probe_packets; + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * Using this is preferred over io_close, because this can return an error. + * Therefore this callback is used instead of io_close by the generic + * libavformat code if io_close is NULL or the default. + * + * @param s the format context + * @param pb IO context to be closed and freed + * @return 0 on success, a negative AVERROR code on failure + */ + int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb); } AVFormatContext; /** diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 3f28f5ad71..4709bc6615 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1546,6 +1546,7 @@ static int dash_init(AVFormatContext *s) ctx->interrupt_callback = s->interrupt_callback; ctx->opaque = s->opaque; ctx->io_close = s->io_close; + ctx->io_close2 = s->io_close2; ctx->io_open = s->io_open; ctx->strict_std_compliance = s->strict_std_compliance; diff --git a/libavformat/fifo.c b/libavformat/fifo.c index 2ee6dde830..86e5d369b5 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -499,6 +499,7 @@ static int fifo_mux_init(AVFormatContext *avf, const AVOutputFormat *oformat, return ret; avf2->opaque = avf->opaque; avf2->io_close = avf->io_close; + avf2->io_close2 = avf->io_close2; avf2->io_open = avf->io_open; avf2->flags = avf->flags; diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 1c2a556375..4d48709bed 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -866,6 +866,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) oc->opaque = s->opaque; oc->io_open = s->io_open; oc->io_close = s->io_close; + oc->io_close2 = s->io_close2; oc->strict_std_compliance = s->strict_std_compliance; av_dict_copy(&oc->metadata, s->metadata, 0); diff --git a/libavformat/internal.h b/libavformat/internal.h index 878c4f1164..eb8239cd3f 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -916,8 +916,16 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op /* * A wrapper around AVFormatContext.io_close that should be used * instead of calling the pointer directly. + * + * @param s AVFormatContext + * @param *pb the AVIOContext to be closed and freed. Can be NULL. + * @return >=0 on success, negative AVERROR in case of failure */ -void ff_format_io_close(AVFormatContext *s, AVIOContext **pb); +int ff_format_io_close(AVFormatContext *s, AVIOContext **pb); + +/* Default io_close callback, not to be used directly, use ff_format_io_close + * instead. */ +void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb); /** * Utility function to check if the file uses http or https protocol diff --git a/libavformat/options.c b/libavformat/options.c index 72c9bdcefe..1634388acb 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -146,9 +146,9 @@ static int io_open_default(AVFormatContext *s, AVIOContext **pb, return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist); } -static void io_close_default(AVFormatContext *s, AVIOContext *pb) +static int io_close2_default(AVFormatContext *s, AVIOContext *pb) { - avio_close(pb); + return avio_close(pb); } AVFormatContext *avformat_alloc_context(void) @@ -162,7 +162,8 @@ AVFormatContext *avformat_alloc_context(void) s = &si->pub; s->av_class = &av_format_context_class; s->io_open = io_open_default; - s->io_close = io_close_default; + s->io_close = ff_format_io_close_default; + s->io_close2= io_close2_default; av_opt_set_defaults(s); diff --git a/libavformat/segment.c b/libavformat/segment.c index d531286c31..e9b0aa4fa8 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -158,6 +158,7 @@ static int segment_mux_init(AVFormatContext *s) av_dict_copy(&oc->metadata, s->metadata, 0); oc->opaque = s->opaque; oc->io_close = s->io_close; + oc->io_close2 = s->io_close2; oc->io_open = s->io_open; oc->flags = s->flags; diff --git a/libavformat/tee.c b/libavformat/tee.c index dfdf70cb08..b3bcd70b9f 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -237,6 +237,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) avf2->opaque = avf->opaque; avf2->io_open = avf->io_open; avf2->io_close = avf->io_close; + avf2->io_close2 = avf->io_close2; avf2->interrupt_callback = avf->interrupt_callback; avf2->flags = avf->flags; avf2->strict_std_compliance = avf->strict_std_compliance; diff --git a/libavformat/utils.c b/libavformat/utils.c index c368b60864..b5a4a09ae8 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1831,11 +1831,22 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op return 0; } -void ff_format_io_close(AVFormatContext *s, AVIOContext **pb) +void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb) { - if (*pb) - s->io_close(s, *pb); + avio_close(pb); +} + +int ff_format_io_close(AVFormatContext *s, AVIOContext **pb) +{ + int ret = 0; + if (*pb) { + if (s->io_close == ff_format_io_close_default || s->io_close == NULL) + ret = s->io_close2(s, *pb); + else + s->io_close(s, *pb); + } *pb = NULL; + return ret; } int ff_is_http_proto(const char *filename) { diff --git a/libavformat/version.h b/libavformat/version.h index 0705ee4112..1623835a78 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 9 -#define LIBAVFORMAT_VERSION_MICRO 102 +#define LIBAVFORMAT_VERSION_MINOR 10 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 466441a0d27daf03c1bf023327da6cc4c610bed3 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 30 Nov 2021 00:15:14 +0100 Subject: [PATCH 462/894] avformat/img2enc: do not ignore IO errors Signed-off-by: Marton Balint --- libavformat/img2enc.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 44895490e6..ded91d6b98 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -121,6 +121,13 @@ static int write_packet_pipe(AVFormatContext *s, AVPacket *pkt) return 0; } +static int write_and_close(AVFormatContext *s, AVIOContext **pb, const unsigned char *buf, int size) +{ + avio_write(*pb, buf, size); + avio_flush(*pb); + return ff_format_io_close(s, pb); +} + static int write_packet(AVFormatContext *s, AVPacket *pkt) { VideoMuxData *img = s->priv_data; @@ -187,24 +194,22 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) ysize *= 2; usize *= 2; } - avio_write(pb[0], pkt->data , ysize); - avio_write(pb[1], pkt->data + ysize , usize); - avio_write(pb[2], pkt->data + ysize + usize, usize); - ff_format_io_close(s, &pb[1]); - ff_format_io_close(s, &pb[2]); - if (desc->nb_components > 3) { - avio_write(pb[3], pkt->data + ysize + 2*usize, ysize); - ff_format_io_close(s, &pb[3]); - } - } else if (img->muxer) { - ret = write_muxed_file(s, pb[0], pkt); - if (ret < 0) + if ((ret = write_and_close(s, &pb[0], pkt->data , ysize)) < 0 || + (ret = write_and_close(s, &pb[1], pkt->data + ysize , usize)) < 0 || + (ret = write_and_close(s, &pb[2], pkt->data + ysize + usize, usize)) < 0) goto fail; + if (desc->nb_components > 3) + ret = write_and_close(s, &pb[3], pkt->data + ysize + 2*usize, ysize); + } else if (img->muxer) { + if ((ret = write_muxed_file(s, pb[0], pkt)) < 0) + goto fail; + ret = ff_format_io_close(s, &pb[0]); } else { - avio_write(pb[0], pkt->data, pkt->size); + ret = write_and_close(s, &pb[0], pkt->data, pkt->size); } - avio_flush(pb[0]); - ff_format_io_close(s, &pb[0]); + if (ret < 0) + goto fail; + for (i = 0; i < nb_renames; i++) { int ret = ff_rename(img->tmp[i], img->target[i], s); if (ret < 0) From 996b13fac4810efc35ff988f523f0c88a3b57ec9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 26 Nov 2021 14:23:16 +0100 Subject: [PATCH 463/894] avfilter: add audio dynamic equalizer filter --- Changelog | 1 + doc/filters.texi | 76 +++++++ libavfilter/Makefile | 1 + libavfilter/af_adynamicequalizer.c | 315 +++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_adynamicequalizer.c diff --git a/Changelog b/Changelog index 13b22f6149..5c6adc0fa7 100644 --- a/Changelog +++ b/Changelog @@ -40,6 +40,7 @@ version : - adynamicsmooth audio filter - libplacebo filter - vflip_vulkan, hflip_vulkan and flip_vulkan filters +- adynamicequalizer audio filter version 4.4: diff --git a/doc/filters.texi b/doc/filters.texi index 8eff460cd9..cffec8168c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -843,6 +843,82 @@ Compute derivative/integral of audio stream. Applying both filters one after another produces original audio. +@section adynamicequalizer + +Apply dynamic equalization to input audio stream. + +A description of the accepted options follows. + +@table @option +@item threshold +Set the detection threshold used to trigger equalization. +Threshold detection is using bandpass filter. +Default value is 0. Allowed range is from 0 to 100. + +@item dfrequency +Set the detection frequency in Hz used for bandpass filter used to trigger equalization. +Default value is 1000 Hz. Allowed range is between 2 and 1000000 Hz. + +@item dqfactor +Set the detection resonance factor for bandpass filter used to trigger equalization. +Default value is 1. Allowed range is from 0.001 to 1000. + +@item tfrequency +Set the target frequency of equalization filter. +Default value is 1000 Hz. Allowed range is between 2 and 1000000 Hz. + +@item tqfactor +Set the target resonance factor for target equalization filter. +Default value is 1. Allowed range is from 0.001 to 1000. + +@item attack +Set the amount of milliseconds the signal from detection has to rise above +the detection threshold before equalization starts. +Default is 20. Allowed range is between 1 and 2000. + +@item release +Set the amount of milliseconds the signal from detection has to fall below the +detection threshold before equalization ends. +Default is 200. Allowed range is between 1 and 2000. + +@item knee +Curve the sharp knee around the detection threshold to calculate +equalization gain more softly. +Default is 1. Allowed range is between 0 and 8. + +@item ratio +Set the ratio by which the equalization gain is raised. +Default is 1. Allowed range is between 1 and 20. + +@item makeup +Set the makeup offset in dB by which the equalization gain is raised. +Default is 0. Allowed range is between 0 and 30. + +@item range +Set the max allowed cut/boost amount in dB. Default is 0. +Allowed range is from 0 to 200. + +@item slew +Set the slew factor. Default is 1. Allowed range is from 1 to 200. + +@item mode +Set the mode of filter operation, can be one of the following: + +@table @samp +@item listen +Output only isolated bandpass signal. +@item cut +Cut frequencies above detection threshold. +@item boost +Boost frequencies bellow detection threshold. +@end table +Default mode is @samp{cut}. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section adynamicsmooth Apply dynamic smoothing to input audio stream. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 8744cc3c63..2fe495df28 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -44,6 +44,7 @@ OBJS-$(CONFIG_ADECORRELATE_FILTER) += af_adecorrelate.o OBJS-$(CONFIG_ADELAY_FILTER) += af_adelay.o OBJS-$(CONFIG_ADENORM_FILTER) += af_adenorm.o OBJS-$(CONFIG_ADERIVATIVE_FILTER) += af_aderivative.o +OBJS-$(CONFIG_ADYNAMICEQUALIZER_FILTER) += af_adynamicequalizer.o OBJS-$(CONFIG_ADYNAMICSMOOTH_FILTER) += af_adynamicsmooth.o OBJS-$(CONFIG_AECHO_FILTER) += af_aecho.o OBJS-$(CONFIG_AEMPHASIS_FILTER) += af_aemphasis.o diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c new file mode 100644 index 0000000000..f377a5db3d --- /dev/null +++ b/libavfilter/af_adynamicequalizer.c @@ -0,0 +1,315 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" +#include "hermite.h" + +typedef struct AudioDynamicEqualizerContext { + const AVClass *class; + + double threshold; + double dfrequency; + double dqfactor; + double tfrequency; + double tqfactor; + double ratio; + double range; + double makeup; + double knee; + double slew; + double attack; + double release; + double attack_coef; + double release_coef; + int mode; + + AVFrame *state; +} AudioDynamicEqualizerContext; + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioDynamicEqualizerContext *s = ctx->priv; + + s->state = ff_get_audio_buffer(inlink, 8); + if (!s->state) + return AVERROR(ENOMEM); + + return 0; +} + +static double get_svf(double in, double *m, double *a, double *b) +{ + const double v0 = in; + const double v3 = v0 - b[1]; + const double v1 = a[0] * b[0] + a[1] * v3; + const double v2 = b[1] + a[1] * b[0] + a[2] * v3; + + b[0] = 2. * v1 - b[0]; + b[1] = 2. * v2 - b[1]; + + return m[0] * v0 + m[1] * v1 + m[2] * v2; +} + +static inline double from_dB(double x) +{ + return exp(0.05 * x * M_LN10); +} + +static inline double to_dB(double x) +{ + return 20. * log10(x); +} + +static inline double sqr(double x) +{ + return x * x; +} + +static double get_gain(double in, double srate, double makeup, + double aattack, double iratio, double knee, double range, + double thresdb, double slewfactor, double *state, + double attack_coeff, double release_coeff, double nc) +{ + double width = (6. * knee) + 0.01; + double cdb = 0.; + double Lgain = 1.; + double Lxg, Lxl, Lyg, Lyl, Ly1; + double checkwidth = 0.; + double slewwidth = 1.8; + int attslew = 0; + + Lyg = 0.; + Lxg = to_dB(fabs(in) + DBL_EPSILON); + + Lyg = Lxg + (iratio - 1.) * sqr(Lxg - thresdb + width * .5) / (2. * width); + + checkwidth = 2. * fabs(Lxg - thresdb); + if (2. * (Lxg - thresdb) < -width) { + Lyg = Lxg; + } else if (checkwidth <= width) { + Lyg = thresdb + (Lxg - thresdb) * iratio; + if (checkwidth <= slewwidth) { + if (Lyg >= state[2]) + attslew = 1; + } + } else if (2. * (Lxg-thresdb) > width) { + Lyg = thresdb + (Lxg - thresdb) * iratio; + } + + attack_coeff = attslew ? aattack : attack_coeff; + + Lxl = Lxg - Lyg; + + Ly1 = fmaxf(Lxl, release_coeff * state[1] +(1. - release_coeff) * Lxl); + Lyl = attack_coeff * state[0] + (1. - attack_coeff) * Ly1; + + cdb = -Lyl; + Lgain = from_dB(nc * fmin(cdb - makeup, range)); + + state[0] = Lyl; + state[1] = Ly1; + state[2] = Lyg; + + return Lgain; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioDynamicEqualizerContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const double sample_rate = in->sample_rate; + const double makeup = s->makeup; + const double iratio = 1. / s->ratio; + const double range = s->range; + const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); + const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); + const double threshold = log(s->threshold + DBL_EPSILON); + const double release = s->release_coef; + const double attack = s->attack_coef; + const double dqfactor = s->dqfactor; + const double tqfactor = s->tqfactor; + const double fg = tan(M_PI * tfrequency / sample_rate); + const double dg = tan(M_PI * dfrequency / sample_rate); + const int start = (in->channels * jobnr) / nb_jobs; + const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int mode = s->mode; + const double knee = s->knee; + const double slew = s->slew; + const double aattack = exp(-1000. / ((s->attack + 2.0 * (slew - 1.)) * sample_rate)); + const double nc = mode == 0 ? 1. : -1.; + double da[3], dm[3]; + + { + double k = 1. / dqfactor; + + da[0] = 1. / (1. + dg * (dg + k)); + da[1] = dg * da[0]; + da[2] = dg * da[1]; + + dm[0] = 0.; + dm[1] = 1.; + dm[2] = 0.; + } + + for (int ch = start; ch < end; ch++) { + const double *src = (const double *)in->extended_data[ch]; + double *dst = (double *)out->extended_data[ch]; + double *state = (double *)s->state->extended_data[ch]; + + for (int n = 0; n < out->nb_samples; n++) { + double detect, gain, v, listen; + double fa[3], fm[3]; + + detect = listen = get_svf(src[n], dm, da, state); + detect = fabs(detect); + + gain = get_gain(detect, sample_rate, makeup, + aattack, iratio, knee, range, threshold, slew, + &state[4], attack, release, nc); + + { + double k = 1. / (tqfactor * gain); + + fa[0] = 1. / (1. + fg * (fg + k)); + fa[1] = fg * fa[0]; + fa[2] = fg * fa[1]; + + fm[0] = 1.; + fm[1] = k * (gain * gain - 1.); + fm[2] = 0.; + } + + v = get_svf(src[n], fm, fa, &state[2]); + v = mode == -1 ? listen : v; + dst[n] = ctx->is_disabled ? src[n] : v; + } + } + + return 0; +} + +static double get_coef(double x, double sr) +{ + return exp(-1000. / (x * sr)); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioDynamicEqualizerContext *s = ctx->priv; + ThreadData td; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + s->attack_coef = get_coef(s->attack, in->sample_rate); + s->release_coef = get_coef(s->release, in->sample_rate); + + td.in = in; + td.out = out; + ff_filter_execute(ctx, filter_channels, &td, NULL, + FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioDynamicEqualizerContext *s = ctx->priv; + + av_frame_free(&s->state); +} + +#define OFFSET(x) offsetof(AudioDynamicEqualizerContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption adynamicequalizer_options[] = { + { "threshold", "set detection threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 100, FLAGS }, + { "dfrequency", "set detection frequency", OFFSET(dfrequency), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 2, 1000000, FLAGS }, + { "dqfactor", "set detection Q factor", OFFSET(dqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, + { "tfrequency", "set target frequency", OFFSET(tfrequency), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 2, 1000000, FLAGS }, + { "tqfactor", "set target Q factor", OFFSET(tqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, + { "attack", "set attack duration", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 2000, FLAGS }, + { "release", "set release duration", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=200}, 1, 2000, FLAGS }, + { "knee", "set knee factor", OFFSET(knee), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 8, FLAGS }, + { "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 20, FLAGS }, + { "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 30, FLAGS }, + { "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 200, FLAGS }, + { "slew", "set slew factor", OFFSET(slew), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 200, FLAGS }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, -1, 1, FLAGS, "mode" }, + { "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "mode" }, + { "cut", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, + { "boost", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(adynamicequalizer); + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +const AVFilter ff_af_adynamicequalizer = { + .name = "adynamicequalizer", + .description = NULL_IF_CONFIG_SMALL("Apply Dynamic Equalization of input audio."), + .priv_size = sizeof(AudioDynamicEqualizerContext), + .priv_class = &adynamicequalizer_class, + .uninit = uninit, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9e16b4e71e..ec57a2c49c 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -37,6 +37,7 @@ extern const AVFilter ff_af_adecorrelate; extern const AVFilter ff_af_adelay; extern const AVFilter ff_af_adenorm; extern const AVFilter ff_af_aderivative; +extern const AVFilter ff_af_adynamicequalizer; extern const AVFilter ff_af_adynamicsmooth; extern const AVFilter ff_af_aecho; extern const AVFilter ff_af_aemphasis; diff --git a/libavfilter/version.h b/libavfilter/version.h index 0247fb4f9a..0253c911be 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 19 +#define LIBAVFILTER_VERSION_MINOR 20 #define LIBAVFILTER_VERSION_MICRO 100 From b54377b3a7cd427bc121af003f12c36a32169a74 Mon Sep 17 00:00:00 2001 From: Ho Ming Shun Date: Fri, 24 Sep 2021 17:04:35 +0800 Subject: [PATCH 464/894] avcodec/mmaldec: use decoupled dataflow MMAL is an fundamentally an asynchronous decoder, which was a bad fit for the legacy dataflow API. Often multiple packets are enqueued before a flood of frames are returned from MMAL. The previous lockstep dataflow meant that any delay in returning packets from the VPU would cause ctx->queue_decoded_frames to grow with no way of draining the queue. Testing this with mpv streaming from a live RTSP source visibly reduced latency introduced by frames waiting in queue_decoded_frames from roughly 2s to 0. Tested-by: Cameron Gutman Signed-off-by: Ho Ming Shun Signed-off-by: Andreas Rheinhardt --- libavcodec/mmaldec.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 8c7d749742..f0391dfae3 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -83,6 +83,8 @@ typedef struct MMALDecodeContext { // libavcodec API can't return new frames, and we have a logical deadlock. // This is avoided by queuing such buffers here. FFBufferEntry *waiting_buffers, *waiting_buffers_tail; + /* Packet used to hold received packets temporarily; not owned by us. */ + AVPacket *pkt; int64_t packets_sent; atomic_int packets_buffered; @@ -355,6 +357,8 @@ static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) MMAL_COMPONENT_T *decoder; int ret = 0; + ctx->pkt = avctx->internal->in_pkt; + bcm_host_init(); if (mmal_vc_init()) { @@ -570,6 +574,7 @@ static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, done: av_buffer_unref(&buf); + av_packet_unref(avpkt); return ret; } @@ -655,6 +660,12 @@ static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, avctx->pix_fmt, avctx->width, avctx->height); } + frame->sample_aspect_ratio = avctx->sample_aspect_ratio; + frame->width = avctx->width; + frame->width = avctx->width; + frame->height = avctx->height; + frame->format = avctx->pix_fmt; + frame->pts = buffer->pts == MMAL_TIME_UNKNOWN ? AV_NOPTS_VALUE : buffer->pts; frame->pkt_dts = AV_NOPTS_VALUE; @@ -763,12 +774,12 @@ done: return ret; } -static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int ffmmal_receive_frame(AVCodecContext *avctx, AVFrame *frame) { MMALDecodeContext *ctx = avctx->priv_data; - AVFrame *frame = data; + AVPacket *const avpkt = ctx->pkt; int ret = 0; + int got_frame = 0; if (avctx->extradata_size && !ctx->extradata_sent) { AVPacket pkt = {0}; @@ -780,7 +791,11 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, return ret; } - if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0) + ret = ff_decode_get_packet(avctx, avpkt); + if (ret == 0) { + if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0) + return ret; + } else if (ret < 0 && !(ret == AVERROR(EAGAIN))) return ret; if ((ret = ffmmal_fill_input_port(avctx)) < 0) @@ -789,7 +804,7 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ffmmal_fill_output_port(avctx)) < 0) return ret; - if ((ret = ffmmal_read_frame(avctx, frame, got_frame)) < 0) + if ((ret = ffmmal_read_frame(avctx, frame, &got_frame)) < 0) return ret; // ffmmal_read_frame() can block for a while. Since the decoder is @@ -801,7 +816,10 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ffmmal_fill_input_port(avctx)) < 0) return ret; - return ret; + if (!got_frame && ret == 0) + return AVERROR(EAGAIN); + else + return ret; } static const AVCodecHWConfigInternal *const mmal_hw_configs[] = { @@ -833,7 +851,7 @@ static const AVOption options[]={ .priv_data_size = sizeof(MMALDecodeContext), \ .init = ffmmal_init_decoder, \ .close = ffmmal_close_decoder, \ - .decode = ffmmal_decode, \ + .receive_frame = ffmmal_receive_frame, \ .flush = ffmmal_flush, \ .priv_class = &ffmmal_##NAME##_dec_class, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ From 6f0e8b998a91f0ad9a260b01d8ff29efdf3321d3 Mon Sep 17 00:00:00 2001 From: Ho Ming Shun Date: Fri, 24 Sep 2021 17:04:37 +0800 Subject: [PATCH 465/894] avcodec/mmaldec: re-use AVPacket for extra_data extra_data and normal packets (from ff_decode_get_packet) processing do not overlap, thus we can re-use the spare AVPacket to send to ffmmal_add_packet. Furthermore, this removes allocation of AVPacket on the stack and stops using deprecated av_init_packet. Tested-by: Cameron Gutman Signed-off-by: Ho Ming Shun --- libavcodec/mmaldec.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index f0391dfae3..f1bcaed0ff 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -782,12 +782,10 @@ static int ffmmal_receive_frame(AVCodecContext *avctx, AVFrame *frame) int got_frame = 0; if (avctx->extradata_size && !ctx->extradata_sent) { - AVPacket pkt = {0}; - av_init_packet(&pkt); - pkt.data = avctx->extradata; - pkt.size = avctx->extradata_size; + avpkt->data = avctx->extradata; + avpkt->size = avctx->extradata_size; ctx->extradata_sent = 1; - if ((ret = ffmmal_add_packet(avctx, &pkt, 1)) < 0) + if ((ret = ffmmal_add_packet(avctx, avpkt, 1)) < 0) return ret; } From dd779749f05fd3a786857b06ee4efc5e193bf90e Mon Sep 17 00:00:00 2001 From: Ho Ming Shun Date: Fri, 24 Sep 2021 17:04:38 +0800 Subject: [PATCH 466/894] avcodec/mmaldec: fix pointer type warning Tested-by: Cameron Gutman Signed-off-by: Ho Ming Shun --- libavcodec/mmaldec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index f1bcaed0ff..b0140170f2 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -656,7 +656,7 @@ static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, av_image_fill_arrays(src, linesize, buffer->data + buffer->type->video.offset[0], avctx->pix_fmt, w, h, 1); - av_image_copy(frame->data, frame->linesize, src, linesize, + av_image_copy(frame->data, frame->linesize, (const uint8_t **)src, linesize, avctx->pix_fmt, avctx->width, avctx->height); } From 9644ee224f56118e5b1ac4edc1b088a6a6ac2ac7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 9 Dec 2021 12:37:18 +0100 Subject: [PATCH 467/894] avcodec/mmaldec: Avoid creating unnecessary reference, simplify code ffmal_add_packet() basically duplicated the logic in av_packet_make_refcounted() with the added twist that it always created a reference even if one is already available. This commit stops doing this. Tested-by: Cameron Gutman Signed-off-by: Andreas Rheinhardt --- libavcodec/mmaldec.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index b0140170f2..0a1905b3a0 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -485,29 +485,19 @@ static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, int is_extradata) { MMALDecodeContext *ctx = avctx->priv_data; - AVBufferRef *buf = NULL; + const AVBufferRef *buf = NULL; int size = 0; uint8_t *data = (uint8_t *)""; uint8_t *start; int ret = 0; if (avpkt->size) { - if (avpkt->buf) { - buf = av_buffer_ref(avpkt->buf); - size = avpkt->size; - data = avpkt->data; - } else { - buf = av_buffer_alloc(avpkt->size); - if (buf) { - memcpy(buf->data, avpkt->data, avpkt->size); - size = buf->size; - data = buf->data; - } - } - if (!buf) { - ret = AVERROR(ENOMEM); + ret = av_packet_make_refcounted(avpkt); + if (ret < 0) goto done; - } + buf = avpkt->buf; + data = avpkt->data; + size = avpkt->size; if (!is_extradata) ctx->packets_sent++; } else { @@ -573,7 +563,6 @@ static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, } while (size); done: - av_buffer_unref(&buf); av_packet_unref(avpkt); return ret; } From 7fe5c7f02dbcda8494150ca79922e4994399274b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 9 Dec 2021 12:58:02 +0100 Subject: [PATCH 468/894] avcodec/mmaldec: Deduplicate AVClasses Possible now that the child_class_next API is gone. Tested-by: Cameron Gutman Signed-off-by: Andreas Rheinhardt --- libavcodec/mmaldec.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 0a1905b3a0..cd645189d9 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -820,16 +820,14 @@ static const AVOption options[]={ {NULL} }; -#define FFMMAL_DEC_CLASS(NAME) \ - static const AVClass ffmmal_##NAME##_dec_class = { \ - .class_name = "mmal_" #NAME "_dec", \ - .item_name = av_default_item_name, \ - .option = options, \ - .version = LIBAVUTIL_VERSION_INT, \ - }; +static const AVClass ffmmal_dec_class = { + .class_name = "mmal_dec", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; #define FFMMAL_DEC(NAME, ID) \ - FFMMAL_DEC_CLASS(NAME) \ const AVCodec ff_##NAME##_mmal_decoder = { \ .name = #NAME "_mmal", \ .long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \ @@ -840,7 +838,7 @@ static const AVOption options[]={ .close = ffmmal_close_decoder, \ .receive_frame = ffmmal_receive_frame, \ .flush = ffmmal_flush, \ - .priv_class = &ffmmal_##NAME##_dec_class, \ + .priv_class = &ffmmal_dec_class, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ From 38fbe6a34cfe48c91156e26806aeb81e0dd09f77 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 18 Nov 2021 14:58:54 +0800 Subject: [PATCH 469/894] avformat/hlsenc: add hls_segment_options correct the segment options name Because the hls_ts_options will be misunderstand by user that only can be used in mpegts segments option. So add this option for segments. Signed-off-by: Steven Liu --- doc/muxers.texi | 4 ++++ libavformat/hlsenc.c | 1 + 2 files changed, 5 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index 7eee8c1be6..287ea569fd 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -919,6 +919,10 @@ This example will create a directory hierarchy 2016/02/15 (if any of them do not produce the playlist, @file{out.m3u8}, and segment files: @file{2016/02/15/file-20160215-1455569023.ts}, @file{2016/02/15/file-20160215-1455569024.ts}, etc. +@item hls_segment_options @var{options_list} +Set output format options using a :-separated list of key=value +parameters. Values containing @code{:} special characters must be +escaped. @item hls_key_info_file @var{key_info_file} Use the information in @var{key_info_file} for segment encryption. The first diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 4d48709bed..b75c1cc746 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -3106,6 +3106,7 @@ static const AVOption options[] = { {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E}, {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"hls_segment_options","set segments files format options of hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E}, {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, {"hls_key_info_file", "file with key URI and key file path", OFFSET(key_info_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E}, From 6cf55b9da2b41d5c2b8a0b6e4405dd84858cae35 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 18 Nov 2021 14:58:55 +0800 Subject: [PATCH 470/894] avformat/hlsenc: deprecate hls_ts_options option Because the hls_ts_options will be misunderstand by user, and then user can use hls_segment_options instead of hls_ts_options. Signed-off-by: Steven Liu --- doc/muxers.texi | 1 + libavformat/hlsenc.c | 4 +++- libavformat/version.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 287ea569fd..1ea98a69a3 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -799,6 +799,7 @@ were recently referenced in the playlist. Default value is 1, meaning segments o Set output format options using a :-separated list of key=value parameters. Values containing @code{:} special characters must be escaped. +@code{hls_ts_options} is deprecated, use hls_segment_options instead of it.. @item hls_start_number_source Start the playlist sequence number (@code{#EXT-X-MEDIA-SEQUENCE}) according to the specified source. diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index b75c1cc746..459129818a 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -3101,7 +3101,9 @@ static const AVOption options[] = { {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E}, {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, {"hls_delete_threshold", "set number of unreferenced segments to keep before deleting", OFFSET(hls_delete_threshold), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E}, - {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E}, +#if FF_HLS_TS_OPTIONS + {"hls_ts_options","set hls mpegts list of options for the container format used for hls (deprecated, use hls_segment_options instead of it.)", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E | AV_OPT_FLAG_DEPRECATED}, +#endif {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E}, {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, diff --git a/libavformat/version.h b/libavformat/version.h index 1623835a78..379a68cc7c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -58,6 +58,7 @@ #define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_HLS_TS_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) From 2f28f6c4b9bd31f0928cbbabae9a2ae41582b1e6 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 4 Dec 2021 10:24:01 +0800 Subject: [PATCH 471/894] avformat/rtpdec_rfc4175: cosmetic changes Signed-off-by: Limin Wang --- libavformat/rtpdec_rfc4175.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index 7feefd2fff..a66e00d5fe 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -195,17 +195,17 @@ static int rfc4175_parse_sdp_line(AVFormatContext *s, int st_index, static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt, int stream_index) { - int ret; + int ret; - pkt->stream_index = stream_index; - ret = av_packet_from_data(pkt, data->frame, data->frame_size); - if (ret < 0) { - av_freep(&data->frame); - } + pkt->stream_index = stream_index; + ret = av_packet_from_data(pkt, data->frame, data->frame_size); + if (ret < 0) { + av_freep(&data->frame); + } - data->frame = NULL; + data->frame = NULL; - return ret; + return ret; } static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, From 571e8ca2ddb90a05e0e0091110f8aeed78620edd Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 10 Dec 2021 18:15:46 +0800 Subject: [PATCH 472/894] avfilter/af_astats: improve options descriptions Signed-off-by: Limin Wang --- doc/filters.texi | 7 ++++--- libavfilter/af_astats.c | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index cffec8168c..da95688c53 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2962,16 +2962,17 @@ this @code{lavfi.astats.Overall.Peak_count}. For description what each key means read below. @item reset -Set number of frame after which stats are going to be recalculated. +Set the number of frames over which cumulative stats are calculated before +being reset Default is disabled. @item measure_perchannel -Select the entries which need to be measured per channel. The metadata keys can +Select the parameters which are measured per channel. The metadata keys can be used as flags, default is @option{all} which measures everything. @option{none} disables all per channel measurement. @item measure_overall -Select the entries which need to be measured overall. The metadata keys can +Select the parameters which are measured overall. The metadata keys can be used as flags, default is @option{all} which measures everything. @option{none} disables all overall measurement. diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index d0810b5dd4..6c79257cb4 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -114,8 +114,8 @@ typedef struct AudioStatsContext { static const AVOption astats_options[] = { { "length", "set the window length", OFFSET(time_constant), AV_OPT_TYPE_DOUBLE, {.dbl=.05}, 0, 10, FLAGS }, { "metadata", "inject metadata in the filtergraph", OFFSET(metadata), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, - { "reset", "recalculate stats after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, - { "measure_perchannel", "only measure_perchannel these per-channel statistics", OFFSET(measure_perchannel), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, + { "reset", "Set the number of frames over which cumulative stats are calculated before being reset", OFFSET(reset_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "measure_perchannel", "Select the parameters which are measured per channel", OFFSET(measure_perchannel), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, { "none" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NONE }, 0, 0, FLAGS, "measure" }, { "all" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ALL }, 0, 0, FLAGS, "measure" }, { "DC_offset" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_DC_OFFSET }, 0, 0, FLAGS, "measure" }, @@ -143,7 +143,7 @@ static const AVOption astats_options[] = { { "Number_of_NaNs" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_NANS }, 0, 0, FLAGS, "measure" }, { "Number_of_Infs" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_INFS }, 0, 0, FLAGS, "measure" }, { "Number_of_denormals" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_DENORMALS }, 0, 0, FLAGS, "measure" }, - { "measure_overall", "only measure_perchannel these overall statistics", OFFSET(measure_overall), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, + { "measure_overall", "Select the parameters which are measured overall", OFFSET(measure_overall), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, { NULL } }; From 9a840ffa176038d44e0197283590f891b2cf9eeb Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Wed, 15 Dec 2021 11:51:04 +0800 Subject: [PATCH 473/894] avutil: [loongarch] Add support for loongarch SIMD. LSX and LASX is loongarch SIMD extention. They are enabled by default if compiler support it, and can be disabled with '--disable-lsx' '--disable-lasx'. Change-Id: Ie2608ea61dbd9b7fffadbf0ec2348bad6c124476 Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- Makefile | 2 +- configure | 20 +++++++++-- ffbuild/arch.mak | 4 ++- ffbuild/common.mak | 8 +++++ libavutil/cpu.c | 7 ++++ libavutil/cpu.h | 4 +++ libavutil/cpu_internal.h | 2 ++ libavutil/loongarch/Makefile | 1 + libavutil/loongarch/cpu.c | 69 ++++++++++++++++++++++++++++++++++++ libavutil/loongarch/cpu.h | 31 ++++++++++++++++ libavutil/tests/cpu.c | 3 ++ tests/checkasm/checkasm.c | 3 ++ 12 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 libavutil/loongarch/Makefile create mode 100644 libavutil/loongarch/cpu.c create mode 100644 libavutil/loongarch/cpu.h diff --git a/Makefile b/Makefile index 26c9107237..5b20658b52 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \ ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \ ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \ MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \ - MMI-OBJS OBJS SLIBOBJS HOSTOBJS TESTOBJS + MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS HOSTOBJS TESTOBJS define RESET $(1) := diff --git a/configure b/configure index a7593ec2db..c4afde4c5c 100755 --- a/configure +++ b/configure @@ -452,7 +452,9 @@ Optimization options (experts only): --disable-mipsdspr2 disable MIPS DSP ASE R2 optimizations --disable-msa disable MSA optimizations --disable-mipsfpu disable floating point MIPS optimizations - --disable-mmi disable Loongson SIMD optimizations + --disable-mmi disable Loongson MMI optimizations + --disable-lsx disable Loongson LSX optimizations + --disable-lasx disable Loongson LASX optimizations --disable-fast-unaligned consider unaligned accesses slow Developer options (useful when working on FFmpeg itself): @@ -2081,6 +2083,8 @@ ARCH_EXT_LIST_LOONGSON=" loongson2 loongson3 mmi + lsx + lasx " ARCH_EXT_LIST_X86_SIMD=" @@ -2617,6 +2621,10 @@ power8_deps="vsx" loongson2_deps="mips" loongson3_deps="mips" +mmi_deps_any="loongson2 loongson3" +lsx_deps="loongarch" +lasx_deps="lsx" + mips32r2_deps="mips" mips32r5_deps="mips" mips32r6_deps="mips" @@ -2625,7 +2633,6 @@ mips64r6_deps="mips" mipsfpu_deps="mips" mipsdsp_deps="mips" mipsdspr2_deps="mips" -mmi_deps_any="loongson2 loongson3" msa_deps="mipsfpu" cpunop_deps="i686" @@ -6134,6 +6141,9 @@ EOF ;; esac +elif enabled loongarch; then + enabled lsx && check_inline_asm lsx '"vadd.b $vr0, $vr1, $vr2"' '-mlsx' && append LSXFLAGS '-mlsx' + enabled lasx && check_inline_asm lasx '"xvadd.b $xr0, $xr1, $xr2"' '-mlasx' && append LASXFLAGS '-mlasx' fi check_cc intrinsics_neon arm_neon.h "int16x8_t test = vdupq_n_s16(0)" @@ -7484,6 +7494,10 @@ if enabled ppc; then echo "PPC 4xx optimizations ${ppc4xx-no}" echo "dcbzl available ${dcbzl-no}" fi +if enabled loongarch; then + echo "LSX enabled ${lsx-no}" + echo "LASX enabled ${lasx-no}" +fi echo "debug symbols ${debug-no}" echo "strip symbols ${stripping-no}" echo "optimize for size ${small-no}" @@ -7645,6 +7659,8 @@ ASMSTRIPFLAGS=$ASMSTRIPFLAGS X86ASMFLAGS=$X86ASMFLAGS MSAFLAGS=$MSAFLAGS MMIFLAGS=$MMIFLAGS +LSXFLAGS=$LSXFLAGS +LASXFLAGS=$LASXFLAGS BUILDSUF=$build_suffix PROGSSUF=$progs_suffix FULLNAME=$FULLNAME diff --git a/ffbuild/arch.mak b/ffbuild/arch.mak index e09006efca..997e31e85e 100644 --- a/ffbuild/arch.mak +++ b/ffbuild/arch.mak @@ -8,7 +8,9 @@ OBJS-$(HAVE_MIPSFPU) += $(MIPSFPU-OBJS) $(MIPSFPU-OBJS-yes) OBJS-$(HAVE_MIPSDSP) += $(MIPSDSP-OBJS) $(MIPSDSP-OBJS-yes) OBJS-$(HAVE_MIPSDSPR2) += $(MIPSDSPR2-OBJS) $(MIPSDSPR2-OBJS-yes) OBJS-$(HAVE_MSA) += $(MSA-OBJS) $(MSA-OBJS-yes) -OBJS-$(HAVE_MMI) += $(MMI-OBJS) $(MMI-OBJS-yes) +OBJS-$(HAVE_MMI) += $(MMI-OBJS) $(MMI-OBJS-yes) +OBJS-$(HAVE_LSX) += $(LSX-OBJS) $(LSX-OBJS-yes) +OBJS-$(HAVE_LASX) += $(LASX-OBJS) $(LASX-OBJS-yes) OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes) OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes) diff --git a/ffbuild/common.mak b/ffbuild/common.mak index 268ae61154..0eb831d434 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -59,6 +59,8 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC) COMPILE_NVCC = $(call COMPILE,NVCC) COMPILE_MMI = $(call COMPILE,CC,MMIFLAGS) COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS) +COMPILE_LSX = $(call COMPILE,CC,LSXFLAGS) +COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS) %_mmi.o: %_mmi.c $(COMPILE_MMI) @@ -66,6 +68,12 @@ COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS) %_msa.o: %_msa.c $(COMPILE_MSA) +%_lsx.o: %_lsx.c + $(COMPILE_LSX) + +%_lasx.o: %_lasx.c + $(COMPILE_LASX) + %.o: %.c $(COMPILE_C) diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 4627af4f23..63efb97ffd 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -62,6 +62,8 @@ static int get_cpu_flags(void) return ff_get_cpu_flags_ppc(); if (ARCH_X86) return ff_get_cpu_flags_x86(); + if (ARCH_LOONGARCH) + return ff_get_cpu_flags_loongarch(); return 0; } @@ -168,6 +170,9 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) #elif ARCH_MIPS { "mmi", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI }, .unit = "flags" }, { "msa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA }, .unit = "flags" }, +#elif ARCH_LOONGARCH + { "lsx", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_LSX }, .unit = "flags" }, + { "lasx", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_LASX }, .unit = "flags" }, #endif { NULL }, }; @@ -253,6 +258,8 @@ size_t av_cpu_max_align(void) return ff_get_cpu_max_align_ppc(); if (ARCH_X86) return ff_get_cpu_max_align_x86(); + if (ARCH_LOONGARCH) + return ff_get_cpu_max_align_loongarch(); return 8; } diff --git a/libavutil/cpu.h b/libavutil/cpu.h index afea0640b4..ae443eccad 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -72,6 +72,10 @@ #define AV_CPU_FLAG_MMI (1 << 0) #define AV_CPU_FLAG_MSA (1 << 1) +//Loongarch SIMD extension. +#define AV_CPU_FLAG_LSX (1 << 0) +#define AV_CPU_FLAG_LASX (1 << 1) + /** * Return the flags which specify extensions supported by the CPU. * The returned value is affected by av_force_cpu_flags() if that was used diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index 889764320b..e207b2d480 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -46,11 +46,13 @@ int ff_get_cpu_flags_aarch64(void); int ff_get_cpu_flags_arm(void); int ff_get_cpu_flags_ppc(void); int ff_get_cpu_flags_x86(void); +int ff_get_cpu_flags_loongarch(void); size_t ff_get_cpu_max_align_mips(void); size_t ff_get_cpu_max_align_aarch64(void); size_t ff_get_cpu_max_align_arm(void); size_t ff_get_cpu_max_align_ppc(void); size_t ff_get_cpu_max_align_x86(void); +size_t ff_get_cpu_max_align_loongarch(void); #endif /* AVUTIL_CPU_INTERNAL_H */ diff --git a/libavutil/loongarch/Makefile b/libavutil/loongarch/Makefile new file mode 100644 index 0000000000..2addd9351c --- /dev/null +++ b/libavutil/loongarch/Makefile @@ -0,0 +1 @@ +OBJS += loongarch/cpu.o diff --git a/libavutil/loongarch/cpu.c b/libavutil/loongarch/cpu.c new file mode 100644 index 0000000000..e4b240bc44 --- /dev/null +++ b/libavutil/loongarch/cpu.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "cpu.h" + +#define LOONGARCH_CFG2 0x2 +#define LOONGARCH_CFG2_LSX (1 << 6) +#define LOONGARCH_CFG2_LASX (1 << 7) + +static int cpu_flags_cpucfg(void) +{ + int flags = 0; + uint32_t cfg2 = 0; + + __asm__ volatile( + "cpucfg %0, %1 \n\t" + : "+&r"(cfg2) + : "r"(LOONGARCH_CFG2) + ); + + if (cfg2 & LOONGARCH_CFG2_LSX) + flags |= AV_CPU_FLAG_LSX; + + if (cfg2 & LOONGARCH_CFG2_LASX) + flags |= AV_CPU_FLAG_LASX; + + return flags; +} + +int ff_get_cpu_flags_loongarch(void) +{ +#if defined __linux__ + return cpu_flags_cpucfg(); +#else + /* Assume no SIMD ASE supported */ + return 0; +#endif +} + +size_t ff_get_cpu_max_align_loongarch(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_LASX) + return 32; + if (flags & AV_CPU_FLAG_LSX) + return 16; + + return 8; +} diff --git a/libavutil/loongarch/cpu.h b/libavutil/loongarch/cpu.h new file mode 100644 index 0000000000..1a445c69bc --- /dev/null +++ b/libavutil/loongarch/cpu.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LOONGARCH_CPU_H +#define AVUTIL_LOONGARCH_CPU_H + +#include "libavutil/cpu.h" +#include "libavutil/cpu_internal.h" + +#define have_lsx(flags) CPUEXT(flags, LSX) +#define have_lasx(flags) CPUEXT(flags, LASX) + +#endif /* AVUTIL_LOONGARCH_CPU_H */ diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c index c853371fb3..0a6c0cd32e 100644 --- a/libavutil/tests/cpu.c +++ b/libavutil/tests/cpu.c @@ -77,6 +77,9 @@ static const struct { { AV_CPU_FLAG_BMI2, "bmi2" }, { AV_CPU_FLAG_AESNI, "aesni" }, { AV_CPU_FLAG_AVX512, "avx512" }, +#elif ARCH_LOONGARCH + { AV_CPU_FLAG_LSX, "lsx" }, + { AV_CPU_FLAG_LASX, "lasx" }, #endif { 0 } }; diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index b1353f7cbe..90d080de02 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -236,6 +236,9 @@ static const struct { { "FMA4", "fma4", AV_CPU_FLAG_FMA4 }, { "AVX2", "avx2", AV_CPU_FLAG_AVX2 }, { "AVX-512", "avx512", AV_CPU_FLAG_AVX512 }, +#elif ARCH_LOONGARCH + { "LSX", "lsx", AV_CPU_FLAG_LSX }, + { "LASX", "lasx", AV_CPU_FLAG_LASX }, #endif { NULL } }; From 6038a9eb92b2daac907c941dbb245ed43c350501 Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Wed, 15 Dec 2021 11:51:05 +0800 Subject: [PATCH 474/894] avcodec: [loongarch] Optimize h264_chroma_mc with LASX. ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:170 after :183 Change-Id: I42ff23cc2dc7c32bd1b7e4274da9d9ec87065f20 Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- libavcodec/h264chroma.c | 2 + libavcodec/h264chroma.h | 1 + libavcodec/loongarch/Makefile | 2 + .../loongarch/h264chroma_init_loongarch.c | 37 + libavcodec/loongarch/h264chroma_lasx.c | 1280 +++++++++++ libavcodec/loongarch/h264chroma_lasx.h | 36 + libavutil/loongarch/loongson_intrinsics.h | 1877 +++++++++++++++++ 7 files changed, 3235 insertions(+) create mode 100644 libavcodec/loongarch/Makefile create mode 100644 libavcodec/loongarch/h264chroma_init_loongarch.c create mode 100644 libavcodec/loongarch/h264chroma_lasx.c create mode 100644 libavcodec/loongarch/h264chroma_lasx.h create mode 100644 libavutil/loongarch/loongson_intrinsics.h diff --git a/libavcodec/h264chroma.c b/libavcodec/h264chroma.c index c2f1f30f5a..0ae6c793e1 100644 --- a/libavcodec/h264chroma.c +++ b/libavcodec/h264chroma.c @@ -56,4 +56,6 @@ av_cold void ff_h264chroma_init(H264ChromaContext *c, int bit_depth) ff_h264chroma_init_x86(c, bit_depth); if (ARCH_MIPS) ff_h264chroma_init_mips(c, bit_depth); + if (ARCH_LOONGARCH64) + ff_h264chroma_init_loongarch(c, bit_depth); } diff --git a/libavcodec/h264chroma.h b/libavcodec/h264chroma.h index 5c89fd12df..3259b4935f 100644 --- a/libavcodec/h264chroma.h +++ b/libavcodec/h264chroma.h @@ -36,5 +36,6 @@ void ff_h264chroma_init_arm(H264ChromaContext *c, int bit_depth); void ff_h264chroma_init_ppc(H264ChromaContext *c, int bit_depth); void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth); void ff_h264chroma_init_mips(H264ChromaContext *c, int bit_depth); +void ff_h264chroma_init_loongarch(H264ChromaContext *c, int bit_depth); #endif /* AVCODEC_H264CHROMA_H */ diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile new file mode 100644 index 0000000000..f8fb54c925 --- /dev/null +++ b/libavcodec/loongarch/Makefile @@ -0,0 +1,2 @@ +OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_init_loongarch.o +LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o diff --git a/libavcodec/loongarch/h264chroma_init_loongarch.c b/libavcodec/loongarch/h264chroma_init_loongarch.c new file mode 100644 index 0000000000..0ca24ecc47 --- /dev/null +++ b/libavcodec/loongarch/h264chroma_init_loongarch.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "h264chroma_lasx.h" +#include "libavutil/attributes.h" +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/h264chroma.h" + +av_cold void ff_h264chroma_init_loongarch(H264ChromaContext *c, int bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_lasx(cpu_flags)) { + if (bit_depth <= 8) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_lasx; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_lasx; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_lasx; + } + } +} diff --git a/libavcodec/loongarch/h264chroma_lasx.c b/libavcodec/loongarch/h264chroma_lasx.c new file mode 100644 index 0000000000..824a78dfc8 --- /dev/null +++ b/libavcodec/loongarch/h264chroma_lasx.c @@ -0,0 +1,1280 @@ +/* + * Loongson LASX optimized h264chroma + * + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "h264chroma_lasx.h" +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +static const uint8_t chroma_mask_arr[64] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 +}; + +static av_always_inline void avc_chroma_hv_8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride_2x << 1; + __m256i src0, src1, src2, src3, src4, out; + __m256i res_hz0, res_hz1, res_hz2, res_vt0, res_vt1; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + DUP2_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src1, src3); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP2_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src1, src3); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1); + res_hz2 = __lasx_xvdp2_h_bu(src3, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1); + res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1); + out = __lasx_xvssrarni_bu_h(res_vt1, res_vt0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hv_8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res_hz0, res_hz1, res_hz2, res_hz3, res_hz4; + __m256i res_vt0, res_vt1, res_vt2, res_vt3; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src6, src5, 0x20, + src8, src7, 0x20, src1, src3, src5, src7); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP4_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src5, src5, mask, src7, + src7, mask, src1, src3, src5, src7); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src3, + coeff_hz_vec, src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + res_hz4 = __lasx_xvdp2_h_bu(src7, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_vt2 = __lasx_xvmul_h(res_hz3, coeff_vt_vec0); + res_vt3 = __lasx_xvmul_h(res_hz4, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_hz2 = __lasx_xvpermi_q(res_hz2, res_hz3, 0x3); + res_hz3 = __lasx_xvpermi_q(res_hz3, res_hz4, 0x3); + DUP4_ARG3(__lasx_xvmadd_h, res_vt0, res_hz0, coeff_vt_vec1, res_vt1, res_hz1, coeff_vt_vec1, + res_vt2, res_hz2, coeff_vt_vec1, res_vt3, res_hz3, coeff_vt_vec1, + res_vt0, res_vt1, res_vt2, res_vt3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res_vt1, res_vt0, 6, res_vt3, res_vt2, 6, out0, out1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i src0, src1, src2, src3, out; + __m256i res0, res1; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src1, src2); + src3 = __lasx_xvldx(src, stride_3x); + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2); + DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); + +} + +static av_always_inline void avc_chroma_hz_8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + src += stride_4x; + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src5, src6); + src7 = __lasx_xvldx(src, stride_3x); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, 0x20, + src7, src6, 0x20, src0, src2, src4, src6); + DUP4_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src4, src4, mask, + src6, src6, mask, src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6, + coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_nonmult_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + uint32_t row; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, out; + __m256i res0, res1; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + mask = __lasx_xvld(chroma_mask_arr, 0); + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + + for (row = height >> 2; row--;) { + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src0, src1, src2, src3); + src += stride_4x; + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2); + DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); + dst += stride_4x; + } + + if ((height & 3)) { + src0 = __lasx_xvld(src, 0); + src1 = __lasx_xvldx(src, stride); + src1 = __lasx_xvpermi_q(src1, src0, 0x20); + src0 = __lasx_xvshuf_b(src1, src1, mask); + res0 = __lasx_xvdp2_h_bu(src0, coeff_vec); + out = __lasx_xvssrarni_bu_h(res0, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + dst += stride; + __lasx_xvstelm_d(out, dst, 0, 2); + } +} + +static av_always_inline void avc_chroma_vt_8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i src0, src1, src2, src3, src4, out; + __m256i res0, res1; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, 0x20, + src4, src3, 0x20, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_vt_8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, 0x20, + src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, 0x20, + src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, + src6, coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void copy_width8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + uint64_t tmp[8]; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride_2] \n\t" + "ldx.d %[tmp3], %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "ld.d %[tmp4], %[src], 0x0 \n\t" + "ldx.d %[tmp5], %[src], %[stride] \n\t" + "ldx.d %[tmp6], %[src], %[stride_2] \n\t" + "ldx.d %[tmp7], %[src], %[stride_3] \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride_2] \n\t" + "stx.d %[tmp3], %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "st.d %[tmp4], %[dst], 0x0 \n\t" + "stx.d %[tmp5], %[dst], %[stride] \n\t" + "stx.d %[tmp6], %[dst], %[stride_2] \n\t" + "stx.d %[tmp7], %[dst], %[stride_3] \n\t" + : [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]), + [tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]), + [tmp4]"=&r"(tmp[4]), [tmp5]"=&r"(tmp[5]), + [tmp6]"=&r"(tmp[6]), [tmp7]"=&r"(tmp[7]), + [dst]"+&r"(dst), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +static av_always_inline void copy_width8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + uint64_t tmp[4]; + ptrdiff_t stride_2, stride_3; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride_2] \n\t" + "ldx.d %[tmp3], %[src], %[stride_3] \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride_2] \n\t" + "stx.d %[tmp3], %[dst], %[stride_3] \n\t" + : [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]), + [tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3) + : [stride]"r"(stride), [dst]"r"(dst), [src]"r"(src) + : "memory" + ); +} + +static void avc_chroma_hv_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hv_8x4_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } else if (8 == height) { + avc_chroma_hv_8x8_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } +} + +static void avc_chroma_hv_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1) +{ + ptrdiff_t stride_2 = stride << 1; + __m256i src0, src1, src2; + __m256i res_hz, res_vt; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + __m256i coeff_vt_vec = __lasx_xvpermi_q(coeff_vt_vec1, coeff_vt_vec0, 0x02); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src1, src2); + DUP2_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src0, src1); + src0 = __lasx_xvpermi_q(src0, src1, 0x02); + res_hz = __lasx_xvdp2_h_bu(src0, coeff_hz_vec); + res_vt = __lasx_xvmul_h(res_hz, coeff_vt_vec); + res_hz = __lasx_xvpermi_q(res_hz, res_vt, 0x01); + res_vt = __lasx_xvadd_h(res_hz, res_vt); + res_vt = __lasx_xvssrarni_bu_h(res_vt, res_vt, 6); + __lasx_xvstelm_w(res_vt, dst, 0, 0); + __lasx_xvstelm_w(res_vt, dst + stride, 0, 1); +} + +static void avc_chroma_hv_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4; + __m256i res_hz0, res_hz1, res_vt0, res_vt1; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src3, src2, mask, + src4, src3, mask, src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src1, src3, 0x02, src0, src1); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1); + DUP2_ARG2(__lasx_xvmul_h, res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); + res_hz0 = __lasx_xvadd_h(res_vt0, res_vt1); + res_hz0 = __lasx_xvssrarni_bu_h(res_hz0, res_hz0, 6); + __lasx_xvstelm_w(res_hz0, dst, 0, 0); + __lasx_xvstelm_w(res_hz0, dst + stride, 0, 1); + __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 5); +} + +static void avc_chroma_hv_4x8_lasx(uint8_t *src, uint8_t * dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i res_hz0, res_hz1, res_hz2, res_hz3; + __m256i res_vt0, res_vt1, res_vt2, res_vt3; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + src += stride_4; + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src3, src2, mask, + src4, src3, mask, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvshuf_b, src5, src4, mask, src6, src5, mask, src7, src6, mask, + src8, src7, mask, src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src1, src3, 0x02, src4, src6, 0x02, + src5, src7, 0x02, src0, src1, src4, src5); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src4, coeff_hz_vec, + src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + DUP4_ARG2(__lasx_xvmul_h, res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_hz2, + coeff_vt_vec1, res_hz3, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, res_vt3); + DUP2_ARG2(__lasx_xvadd_h, res_vt0, res_vt1, res_vt2, res_vt3, res_vt0, res_vt2); + res_hz0 = __lasx_xvssrarni_bu_h(res_vt2, res_vt0, 6); + __lasx_xvstelm_w(res_hz0, dst, 0, 0); + __lasx_xvstelm_w(res_hz0, dst + stride, 0, 1); + __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 5); + dst += stride_4; + __lasx_xvstelm_w(res_hz0, dst, 0, 2); + __lasx_xvstelm_w(res_hz0, dst + stride, 0, 3); + __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 6); + __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 7); +} + +static void avc_chroma_hv_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1, + int32_t height) +{ + if (8 == height) { + avc_chroma_hv_4x8_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } else if (4 == height) { + avc_chroma_hv_4x4_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } else if (2 == height) { + avc_chroma_hv_4x2_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } +} + +static void avc_chroma_hz_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + __m256i src0, src1; + __m256i res, mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + src1 = __lasx_xvldx(src, stride); + src0 = __lasx_xvshuf_b(src1, src0, mask); + res = __lasx_xvdp2_h_bu(src0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); +} + +static void avc_chroma_hz_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + __m256i src0, src1, src2, src3; + __m256i res, mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src1, src2); + src3 = __lasx_xvldx(src, stride_3); + DUP2_ARG3(__lasx_xvshuf_b, src1, src0, mask, src3, src2, mask, src0, src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + res = __lasx_xvdp2_h_bu(src0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); + __lasx_xvstelm_w(res, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res, dst + stride_3, 0, 5); +} + +static void avc_chroma_hz_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i res0, res1, mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + src += stride_4; + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src5, src6); + src7 = __lasx_xvldx(src, stride_3); + DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src3, src2, mask, src5, src4, mask, + src7, src6, mask, src0, src2, src4, src6); + DUP2_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src4, src6, 0x02, src0, src4); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src4, coeff_vec, res0, res1); + res0 = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_w(res0, dst, 0, 0); + __lasx_xvstelm_w(res0, dst + stride, 0, 1); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 5); + dst += stride_4; + __lasx_xvstelm_w(res0, dst, 0, 2); + __lasx_xvstelm_w(res0, dst + stride, 0, 3); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 6); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 7); +} + +static void avc_chroma_hz_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (8 == height) { + avc_chroma_hz_4x8_lasx(src, dst, stride, coeff0, coeff1); + } else if (4 == height) { + avc_chroma_hz_4x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (2 == height) { + avc_chroma_hz_4x2_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avc_chroma_hz_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hz_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_hz_8x8_lasx(src, dst, stride, coeff0, coeff1); + } else { + avc_chroma_hz_nonmult_lasx(src, dst, stride, coeff0, coeff1, height); + } +} + +static void avc_chroma_vt_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + __m256i src0, src1, src2; + __m256i tmp0, tmp1; + __m256i res; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + src0 = __lasx_xvld(src, 0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride << 1, src1, src2); + DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, tmp0, tmp1); + tmp0 = __lasx_xvilvl_d(tmp1, tmp0); + res = __lasx_xvdp2_h_bu(tmp0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); +} + +static void avc_chroma_vt_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4; + __m256i tmp0, tmp1, tmp2, tmp3; + __m256i res; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + src0 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, src3, src2, src4, src3, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); + tmp0 = __lasx_xvpermi_q(tmp0, tmp2, 0x02); + res = __lasx_xvdp2_h_bu(tmp0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); + __lasx_xvstelm_w(res, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res, dst + stride_3, 0, 5); +} + +static void avc_chroma_vt_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i res0, res1; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + src += stride_4; + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src5, src6, src7, src8); + DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, src3, src2, src4, src3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lasx_xvilvl_b, src5, src4, src6, src5, src7, src6, src8, src7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, + tmp0, tmp2, tmp4, tmp6); + tmp0 = __lasx_xvpermi_q(tmp0, tmp2, 0x02); + tmp4 = __lasx_xvpermi_q(tmp4, tmp6, 0x02); + DUP2_ARG2(__lasx_xvdp2_h_bu, tmp0, coeff_vec, tmp4, coeff_vec, res0, res1); + res0 = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_w(res0, dst, 0, 0); + __lasx_xvstelm_w(res0, dst + stride, 0, 1); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 5); + dst += stride_4; + __lasx_xvstelm_w(res0, dst, 0, 2); + __lasx_xvstelm_w(res0, dst + stride, 0, 3); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 6); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 7); +} + +static void avc_chroma_vt_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (8 == height) { + avc_chroma_vt_4x8_lasx(src, dst, stride, coeff0, coeff1); + } else if (4 == height) { + avc_chroma_vt_4x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (2 == height) { + avc_chroma_vt_4x2_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avc_chroma_vt_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (4 == height) { + avc_chroma_vt_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_vt_8x8_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void copy_width4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t height) +{ + uint32_t tp0, tp1, tp2, tp3, tp4, tp5, tp6, tp7; + + if (8 == height) { + ptrdiff_t stride_2, stride_3, stride_4; + + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "ld.wu %[tp0], %[src], 0 \n\t" + "ldx.wu %[tp1], %[src], %[stride] \n\t" + "ldx.wu %[tp2], %[src], %[stride_2] \n\t" + "ldx.wu %[tp3], %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "ld.wu %[tp4], %[src], 0 \n\t" + "ldx.wu %[tp5], %[src], %[stride] \n\t" + "ldx.wu %[tp6], %[src], %[stride_2] \n\t" + "ldx.wu %[tp7], %[src], %[stride_3] \n\t" + "st.w %[tp0], %[dst], 0 \n\t" + "stx.w %[tp1], %[dst], %[stride] \n\t" + "stx.w %[tp2], %[dst], %[stride_2] \n\t" + "stx.w %[tp3], %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "st.w %[tp4], %[dst], 0 \n\t" + "stx.w %[tp5], %[dst], %[stride] \n\t" + "stx.w %[tp6], %[dst], %[stride_2] \n\t" + "stx.w %[tp7], %[dst], %[stride_3] \n\t" + : [stride_2]"+&r"(stride_2), [stride_3]"+&r"(stride_3), [stride_4]"+&r"(stride_4), + [src]"+&r"(src), [dst]"+&r"(dst), [tp0]"+&r"(tp0), [tp1]"+&r"(tp1), + [tp2]"+&r"(tp2), [tp3]"+&r"(tp3), [tp4]"+&r"(tp4), [tp5]"+&r"(tp5), + [tp6]"+&r"(tp6), [tp7]"+&r"(tp7) + : [stride]"r"(stride) + : "memory" + ); + } else if (4 == height) { + ptrdiff_t stride_2, stride_3; + + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "ld.wu %[tp0], %[src], 0 \n\t" + "ldx.wu %[tp1], %[src], %[stride] \n\t" + "ldx.wu %[tp2], %[src], %[stride_2] \n\t" + "ldx.wu %[tp3], %[src], %[stride_3] \n\t" + "st.w %[tp0], %[dst], 0 \n\t" + "stx.w %[tp1], %[dst], %[stride] \n\t" + "stx.w %[tp2], %[dst], %[stride_2] \n\t" + "stx.w %[tp3], %[dst], %[stride_3] \n\t" + : [stride_2]"+&r"(stride_2), [stride_3]"+&r"(stride_3), + [src]"+&r"(src), [dst]"+&r"(dst), [tp0]"+&r"(tp0), [tp1]"+&r"(tp1), + [tp2]"+&r"(tp2), [tp3]"+&r"(tp3) + : [stride]"r"(stride) + : "memory" + ); + } else if (2 == height) { + __asm__ volatile ( + "ld.wu %[tp0], %[src], 0 \n\t" + "ldx.wu %[tp1], %[src], %[stride] \n\t" + "st.w %[tp0], %[dst], 0 \n\t" + "stx.w %[tp1], %[dst], %[stride] \n\t" + : [tp0]"+&r"(tp0), [tp1]"+&r"(tp1) + : [src]"r"(src), [dst]"r"(dst), [stride]"r"(stride) + : "memory" + ); + } +} + +static void copy_width8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t height) +{ + if (8 == height) { + copy_width8x8_lasx(src, dst, stride); + } else if (4 == height) { + copy_width8x4_lasx(src, dst, stride); + } +} + +void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int height, int x, int y) +{ + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + if(x && y) { + avc_chroma_hv_4w_lasx(src, dst, stride, x, (8 - x), y, (8 - y), height); + } else if (x) { + avc_chroma_hz_4w_lasx(src, dst, stride, x, (8 - x), height); + } else if (y) { + avc_chroma_vt_4w_lasx(src, dst, stride, y, (8 - y), height); + } else { + copy_width4_lasx(src, dst, stride, height); + } +} + +void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int height, int x, int y) +{ + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + if (!(x || y)) { + copy_width8_lasx(src, dst, stride, height); + } else if (x && y) { + avc_chroma_hv_8w_lasx(src, dst, stride, x, (8 - x), y, (8 - y), height); + } else if (x) { + avc_chroma_hz_8w_lasx(src, dst, stride, x, (8 - x), height); + } else { + avc_chroma_vt_8w_lasx(src, dst, stride, y, (8 - y), height); + } +} + +static av_always_inline void avc_chroma_hv_and_aver_dst_8x4_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3; + __m256i src0, src1, src2, src3, src4, out; + __m256i res_hz0, res_hz1, res_hz2, res_vt0, res_vt1; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + DUP2_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src1, src3); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP2_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src1, src3); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1); + res_hz2 = __lasx_xvdp2_h_bu(src3, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1); + res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1); + out = __lasx_xvssrarni_bu_h(res_vt1, res_vt0, 6); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + tp0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out = __lasx_xvavgr_bu(out, tp0); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hv_and_aver_dst_8x8_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3, dst0, dst1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res_hz0, res_hz1, res_hz2, res_hz3, res_hz4; + __m256i res_vt0, res_vt1, res_vt2, res_vt3; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src6, src5, 0x20, + src8, src7, 0x20, src1, src3, src5, src7); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP4_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src5, src5, mask, src7, + src7, mask, src1, src3, src5, src7); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src3, + coeff_hz_vec, src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + res_hz4 = __lasx_xvdp2_h_bu(src7, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_vt2 = __lasx_xvmul_h(res_hz3, coeff_vt_vec0); + res_vt3 = __lasx_xvmul_h(res_hz4, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_hz2 = __lasx_xvpermi_q(res_hz2, res_hz3, 0x3); + res_hz3 = __lasx_xvpermi_q(res_hz3, res_hz4, 0x3); + res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1); + res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1); + res_vt2 = __lasx_xvmadd_h(res_vt2, res_hz2, coeff_vt_vec1); + res_vt3 = __lasx_xvmadd_h(res_vt3, res_hz3, coeff_vt_vec1); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res_vt1, res_vt0, 6, res_vt3, res_vt2, 6, + out0, out1); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + dst -= stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst1 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out0 = __lasx_xvavgr_bu(out0, dst0); + out1 = __lasx_xvavgr_bu(out1, dst1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_and_aver_dst_8x4_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i tp0, tp1, tp2, tp3; + __m256i src0, src1, src2, src3, out; + __m256i res0, res1; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + mask = __lasx_xvld(chroma_mask_arr, 0); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2); + DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + tp0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out = __lasx_xvavgr_bu(out, tp0); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_and_aver_dst_8x8_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3, dst0, dst1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + mask = __lasx_xvld(chroma_mask_arr, 0); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src0, src1, src2, src3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, 0x20, + src7, src6, 0x20, src0, src2, src4, src6); + DUP4_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src4, src4, + mask, src6, src6, mask, src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6, + coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + dst -= stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst1 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out0 = __lasx_xvavgr_bu(out0, dst0); + out1 = __lasx_xvavgr_bu(out1, dst1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_vt_and_aver_dst_8x4_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3; + __m256i src0, src1, src2, src3, src4, out; + __m256i res0, res1; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, 0x20, + src4, src3, 0x20, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + tp0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out = __lasx_xvavgr_bu(out, tp0); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_vt_and_aver_dst_8x8_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3, dst0, dst1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, 0x20, + src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, 0x20, + src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6, + coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + dst -= stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst1 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out0 = __lasx_xvavgr_bu(out0, dst0); + out1 = __lasx_xvavgr_bu(out1, dst1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avg_width8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + + src0 = __lasx_xvldrepl_d(src, 0); + src1 = __lasx_xvldrepl_d(src + stride, 0); + src2 = __lasx_xvldrepl_d(src + stride_2x, 0); + src3 = __lasx_xvldrepl_d(src + stride_3x, 0); + dst0 = __lasx_xvldrepl_d(dst, 0); + dst1 = __lasx_xvldrepl_d(dst + stride, 0); + dst2 = __lasx_xvldrepl_d(dst + stride_2x, 0); + dst3 = __lasx_xvldrepl_d(dst + stride_3x, 0); + src0 = __lasx_xvpackev_d(src1,src0); + src2 = __lasx_xvpackev_d(src3,src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + dst0 = __lasx_xvpackev_d(dst1,dst0); + dst2 = __lasx_xvpackev_d(dst3,dst2); + dst0 = __lasx_xvpermi_q(dst0, dst2, 0x02); + dst0 = __lasx_xvavgr_bu(src0, dst0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); + + src += stride_4x; + dst += stride_4x; + src0 = __lasx_xvldrepl_d(src, 0); + src1 = __lasx_xvldrepl_d(src + stride, 0); + src2 = __lasx_xvldrepl_d(src + stride_2x, 0); + src3 = __lasx_xvldrepl_d(src + stride_3x, 0); + dst0 = __lasx_xvldrepl_d(dst, 0); + dst1 = __lasx_xvldrepl_d(dst + stride, 0); + dst2 = __lasx_xvldrepl_d(dst + stride_2x, 0); + dst3 = __lasx_xvldrepl_d(dst + stride_3x, 0); + src0 = __lasx_xvpackev_d(src1,src0); + src2 = __lasx_xvpackev_d(src3,src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + dst0 = __lasx_xvpackev_d(dst1,dst0); + dst2 = __lasx_xvpackev_d(dst3,dst2); + dst0 = __lasx_xvpermi_q(dst0, dst2, 0x02); + dst0 = __lasx_xvavgr_bu(src0, dst0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); +} + +static av_always_inline void avg_width8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + src0 = __lasx_xvldrepl_d(src, 0); + src1 = __lasx_xvldrepl_d(src + stride, 0); + src2 = __lasx_xvldrepl_d(src + stride_2x, 0); + src3 = __lasx_xvldrepl_d(src + stride_3x, 0); + dst0 = __lasx_xvldrepl_d(dst, 0); + dst1 = __lasx_xvldrepl_d(dst + stride, 0); + dst2 = __lasx_xvldrepl_d(dst + stride_2x, 0); + dst3 = __lasx_xvldrepl_d(dst + stride_3x, 0); + src0 = __lasx_xvpackev_d(src1,src0); + src2 = __lasx_xvpackev_d(src3,src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + dst0 = __lasx_xvpackev_d(dst1,dst0); + dst2 = __lasx_xvpackev_d(dst3,dst2); + dst0 = __lasx_xvpermi_q(dst0, dst2, 0x02); + dst0 = __lasx_xvavgr_bu(src0, dst0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); +} + +static void avc_chroma_hv_and_aver_dst_8w_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hv_and_aver_dst_8x4_lasx(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } else if (8 == height) { + avc_chroma_hv_and_aver_dst_8x8_lasx(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } +} + +static void avc_chroma_hz_and_aver_dst_8w_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + if (4 == height) { + avc_chroma_hz_and_aver_dst_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_hz_and_aver_dst_8x8_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avc_chroma_vt_and_aver_dst_8w_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + if (4 == height) { + avc_chroma_vt_and_aver_dst_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_vt_and_aver_dst_8x8_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avg_width8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t height) +{ + if (8 == height) { + avg_width8x8_lasx(src, dst, stride); + } else if (4 == height) { + avg_width8x4_lasx(src, dst, stride); + } +} + +void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int height, int x, int y) +{ + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + if (!(x || y)) { + avg_width8_lasx(src, dst, stride, height); + } else if (x && y) { + avc_chroma_hv_and_aver_dst_8w_lasx(src, dst, stride, x, (8 - x), y, + (8 - y), height); + } else if (x) { + avc_chroma_hz_and_aver_dst_8w_lasx(src, dst, stride, x, (8 - x), height); + } else { + avc_chroma_vt_and_aver_dst_8w_lasx(src, dst, stride, y, (8 - y), height); + } +} diff --git a/libavcodec/loongarch/h264chroma_lasx.h b/libavcodec/loongarch/h264chroma_lasx.h new file mode 100644 index 0000000000..4aac8db8cb --- /dev/null +++ b/libavcodec/loongarch/h264chroma_lasx.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_H264CHROMA_LASX_H +#define AVCODEC_LOONGARCH_H264CHROMA_LASX_H + +#include +#include +#include "libavcodec/h264.h" + +void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); +void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); +void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); + +#endif /* AVCODEC_LOONGARCH_H264CHROMA_LASX_H */ diff --git a/libavutil/loongarch/loongson_intrinsics.h b/libavutil/loongarch/loongson_intrinsics.h new file mode 100644 index 0000000000..6e0439f829 --- /dev/null +++ b/libavutil/loongarch/loongson_intrinsics.h @@ -0,0 +1,1877 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Contributed by Shiyou Yin + * Xiwei Gu + * Lu Wang + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef AVUTIL_LOONGARCH_LOONGSON_INTRINSICS_H +#define AVUTIL_LOONGARCH_LOONGSON_INTRINSICS_H + +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Contributed by Shiyou Yin + * Xiwei Gu + * Lu Wang + * + * This file is a header file for loongarch builtin extention. + * + */ + +#ifndef LOONGSON_INTRINSICS_H +#define LOONGSON_INTRINSICS_H + +/** + * MAJOR version: Macro usage changes. + * MINOR version: Add new functions, or bug fix. + * MICRO version: Comment changes or implementation changes. + */ +#define LSOM_VERSION_MAJOR 1 +#define LSOM_VERSION_MINOR 0 +#define LSOM_VERSION_MICRO 3 + +#define DUP2_ARG1(_INS, _IN0, _IN1, _OUT0, _OUT1) \ +{ \ + _OUT0 = _INS(_IN0); \ + _OUT1 = _INS(_IN1); \ +} + +#define DUP2_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1) \ +{ \ + _OUT0 = _INS(_IN0, _IN1); \ + _OUT1 = _INS(_IN2, _IN3); \ +} + +#define DUP2_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _OUT0, _OUT1) \ +{ \ + _OUT0 = _INS(_IN0, _IN1, _IN2); \ + _OUT1 = _INS(_IN3, _IN4, _IN5); \ +} + +#define DUP4_ARG1(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1, _OUT2, _OUT3) \ +{ \ + DUP2_ARG1(_INS, _IN0, _IN1, _OUT0, _OUT1); \ + DUP2_ARG1(_INS, _IN2, _IN3, _OUT2, _OUT3); \ +} + +#define DUP4_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _IN6, _IN7, \ + _OUT0, _OUT1, _OUT2, _OUT3) \ +{ \ + DUP2_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1); \ + DUP2_ARG2(_INS, _IN4, _IN5, _IN6, _IN7, _OUT2, _OUT3); \ +} + +#define DUP4_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _IN6, _IN7, \ + _IN8, _IN9, _IN10, _IN11, _OUT0, _OUT1, _OUT2, _OUT3) \ +{ \ + DUP2_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _OUT0, _OUT1); \ + DUP2_ARG3(_INS, _IN6, _IN7, _IN8, _IN9, _IN10, _IN11, _OUT2, _OUT3); \ +} + +#ifdef __loongarch_sx +#include +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Outputs - out + * Retrun Type - halfword + * Details : Signed byte elements from in_h are multiplied by + * signed byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * Then the results plus to signed half word elements from in_c. + * Example : out = __lsx_vdp2add_h_b(in_c, in_h, in_l) + * in_c : 1,2,3,4, 1,2,3,4 + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1 + * out : 23,40,41,26, 23,40,41,26 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2add_h_b(__m128i in_c, __m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmaddwev_h_b(in_c, in_h, in_l); + out = __lsx_vmaddwod_h_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Outputs - out + * Retrun Type - halfword + * Details : Unsigned byte elements from in_h are multiplied by + * unsigned byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * The results plus to signed half word elements from in_c. + * Example : out = __lsx_vdp2add_h_b(in_c, in_h, in_l) + * in_c : 1,2,3,4, 1,2,3,4 + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1 + * out : 23,40,41,26, 23,40,41,26 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2add_h_bu(__m128i in_c, __m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmaddwev_h_bu(in_c, in_h, in_l); + out = __lsx_vmaddwod_h_bu(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product & addition of half word vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Outputs - out + * Retrun Type - __m128i + * Details : Signed half word elements from in_h are multiplied by + * signed half word elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * Then the results plus to signed word elements from in_c. + * Example : out = __lsx_vdp2add_h_b(in_c, in_h, in_l) + * in_c : 1,2,3,4 + * in_h : 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1 + * out : 23,40,41,26 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2add_w_h(__m128i in_c, __m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmaddwev_w_h(in_c, in_h, in_l); + out = __lsx_vmaddwod_w_h(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun Type - halfword + * Details : Signed byte elements from in_h are multiplied by + * signed byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * Example : out = __lsx_vdp2_h_b(in_h, in_l) + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1 + * out : 22,38,38,22, 22,38,38,22 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2_h_b(__m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmulwev_h_b(in_h, in_l); + out = __lsx_vmaddwod_h_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun Type - halfword + * Details : Unsigned byte elements from in_h are multiplied by + * unsigned byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * Example : out = __lsx_vdp2_h_bu(in_h, in_l) + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1 + * out : 22,38,38,22, 22,38,38,22 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2_h_bu(__m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmulwev_h_bu(in_h, in_l); + out = __lsx_vmaddwod_h_bu(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun Type - halfword + * Details : Unsigned byte elements from in_h are multiplied by + * signed byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * Example : out = __lsx_vdp2_h_bu_b(in_h, in_l) + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,-1 + * out : 22,38,38,22, 22,38,38,6 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2_h_bu_b(__m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmulwev_h_bu_b(in_h, in_l); + out = __lsx_vmaddwod_h_bu_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun Type - halfword + * Details : Signed byte elements from in_h are multiplied by + * signed byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * Example : out = __lsx_vdp2_w_h(in_h, in_l) + * in_h : 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1 + * out : 22,38,38,22 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2_w_h(__m128i in_h, __m128i in_l) +{ + __m128i out; + + out = __lsx_vmulwev_w_h(in_h, in_l); + out = __lsx_vmaddwod_w_h(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Clip all halfword elements of input vector between min & max + * out = ((_in) < (min)) ? (min) : (((_in) > (max)) ? (max) : (_in)) + * Arguments : Inputs - _in (input vector) + * - min (min threshold) + * - max (max threshold) + * Outputs - out (output vector with clipped elements) + * Return Type - signed halfword + * Example : out = __lsx_vclip_h(_in) + * _in : -8,2,280,249, -8,255,280,249 + * min : 1,1,1,1, 1,1,1,1 + * max : 9,9,9,9, 9,9,9,9 + * out : 1,2,9,9, 1,9,9,9 + * ============================================================================= + */ +static inline __m128i __lsx_vclip_h(__m128i _in, __m128i min, __m128i max) +{ + __m128i out; + + out = __lsx_vmax_h(min, _in); + out = __lsx_vmin_h(max, out); + return out; +} + +/* + * ============================================================================= + * Description : Set each element of vector between 0 and 255 + * Arguments : Inputs - _in + * Outputs - out + * Retrun Type - halfword + * Details : Signed byte elements from _in are clamped between 0 and 255. + * Example : out = __lsx_vclip255_h(_in) + * _in : -8,255,280,249, -8,255,280,249 + * out : 0,255,255,249, 0,255,255,249 + * ============================================================================= + */ +static inline __m128i __lsx_vclip255_h(__m128i _in) +{ + __m128i out; + + out = __lsx_vmaxi_h(_in, 0); + out = __lsx_vsat_hu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Set each element of vector between 0 and 255 + * Arguments : Inputs - _in + * Outputs - out + * Retrun Type - word + * Details : Signed byte elements from _in are clamped between 0 and 255. + * Example : out = __lsx_vclip255_w(_in) + * _in : -8,255,280,249 + * out : 0,255,255,249 + * ============================================================================= + */ +static inline __m128i __lsx_vclip255_w(__m128i _in) +{ + __m128i out; + + out = __lsx_vmaxi_w(_in, 0); + out = __lsx_vsat_wu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Swap two variables + * Arguments : Inputs - _in0, _in1 + * Outputs - _in0, _in1 (in-place) + * Details : Swapping of two input variables using xor + * Example : LSX_SWAP(_in0, _in1) + * _in0 : 1,2,3,4 + * _in1 : 5,6,7,8 + * _in0(out) : 5,6,7,8 + * _in1(out) : 1,2,3,4 + * ============================================================================= + */ +#define LSX_SWAP(_in0, _in1) \ +{ \ + _in0 = __lsx_vxor_v(_in0, _in1); \ + _in1 = __lsx_vxor_v(_in0, _in1); \ + _in0 = __lsx_vxor_v(_in0, _in1); \ +} \ + +/* + * ============================================================================= + * Description : Transpose 4x4 block with word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Details : + * Example : + * 1, 2, 3, 4 1, 5, 9,13 + * 5, 6, 7, 8 to 2, 6,10,14 + * 9,10,11,12 =====> 3, 7,11,15 + * 13,14,15,16 4, 8,12,16 + * ============================================================================= + */ +#define LSX_TRANSPOSE4x4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + __m128i _t0, _t1, _t2, _t3; \ + \ + _t0 = __lsx_vilvl_w(_in1, _in0); \ + _t1 = __lsx_vilvh_w(_in1, _in0); \ + _t2 = __lsx_vilvl_w(_in3, _in2); \ + _t3 = __lsx_vilvh_w(_in3, _in2); \ + _out0 = __lsx_vilvl_d(_t2, _t0); \ + _out1 = __lsx_vilvh_d(_t2, _t0); \ + _out2 = __lsx_vilvl_d(_t3, _t1); \ + _out3 = __lsx_vilvh_d(_t3, _t1); \ +} + +/* + * ============================================================================= + * Description : Transpose 8x8 block with byte elements in vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7 + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + * Details : The rows of the matrix become columns, and the columns become rows. + * Example : LSX_TRANSPOSE8x8_B + * _in0 : 00,01,02,03,04,05,06,07, 00,00,00,00,00,00,00,00 + * _in1 : 10,11,12,13,14,15,16,17, 00,00,00,00,00,00,00,00 + * _in2 : 20,21,22,23,24,25,26,27, 00,00,00,00,00,00,00,00 + * _in3 : 30,31,32,33,34,35,36,37, 00,00,00,00,00,00,00,00 + * _in4 : 40,41,42,43,44,45,46,47, 00,00,00,00,00,00,00,00 + * _in5 : 50,51,52,53,54,55,56,57, 00,00,00,00,00,00,00,00 + * _in6 : 60,61,62,63,64,65,66,67, 00,00,00,00,00,00,00,00 + * _in7 : 70,71,72,73,74,75,76,77, 00,00,00,00,00,00,00,00 + * + * _ out0 : 00,10,20,30,40,50,60,70, 00,00,00,00,00,00,00,00 + * _ out1 : 01,11,21,31,41,51,61,71, 00,00,00,00,00,00,00,00 + * _ out2 : 02,12,22,32,42,52,62,72, 00,00,00,00,00,00,00,00 + * _ out3 : 03,13,23,33,43,53,63,73, 00,00,00,00,00,00,00,00 + * _ out4 : 04,14,24,34,44,54,64,74, 00,00,00,00,00,00,00,00 + * _ out5 : 05,15,25,35,45,55,65,75, 00,00,00,00,00,00,00,00 + * _ out6 : 06,16,26,36,46,56,66,76, 00,00,00,00,00,00,00,00 + * _ out7 : 07,17,27,37,47,57,67,77, 00,00,00,00,00,00,00,00 + * ============================================================================= + */ +#define LSX_TRANSPOSE8x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + __m128i zero = {0}; \ + __m128i shuf8 = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; \ + __m128i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + \ + _t0 = __lsx_vilvl_b(_in2, _in0); \ + _t1 = __lsx_vilvl_b(_in3, _in1); \ + _t2 = __lsx_vilvl_b(_in6, _in4); \ + _t3 = __lsx_vilvl_b(_in7, _in5); \ + _t4 = __lsx_vilvl_b(_t1, _t0); \ + _t5 = __lsx_vilvh_b(_t1, _t0); \ + _t6 = __lsx_vilvl_b(_t3, _t2); \ + _t7 = __lsx_vilvh_b(_t3, _t2); \ + _out0 = __lsx_vilvl_w(_t6, _t4); \ + _out2 = __lsx_vilvh_w(_t6, _t4); \ + _out4 = __lsx_vilvl_w(_t7, _t5); \ + _out6 = __lsx_vilvh_w(_t7, _t5); \ + _out1 = __lsx_vshuf_b(zero, _out0, shuf8); \ + _out3 = __lsx_vshuf_b(zero, _out2, shuf8); \ + _out5 = __lsx_vshuf_b(zero, _out4, shuf8); \ + _out7 = __lsx_vshuf_b(zero, _out6, shuf8); \ +} + +/* + * ============================================================================= + * Description : Transpose 8x8 block with half word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7 + * Outputs - out0, out1, out2, out3, out4, out5, out6, out7 + * Details : + * Example : + * 00,01,02,03,04,05,06,07 00,10,20,30,40,50,60,70 + * 10,11,12,13,14,15,16,17 01,11,21,31,41,51,61,71 + * 20,21,22,23,24,25,26,27 02,12,22,32,42,52,62,72 + * 30,31,32,33,34,35,36,37 to 03,13,23,33,43,53,63,73 + * 40,41,42,43,44,45,46,47 ======> 04,14,24,34,44,54,64,74 + * 50,51,52,53,54,55,56,57 05,15,25,35,45,55,65,75 + * 60,61,62,63,64,65,66,67 06,16,26,36,46,56,66,76 + * 70,71,72,73,74,75,76,77 07,17,27,37,47,57,67,77 + * ============================================================================= + */ +#define LSX_TRANSPOSE8x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + __m128i _s0, _s1, _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + \ + _s0 = __lsx_vilvl_h(_in6, _in4); \ + _s1 = __lsx_vilvl_h(_in7, _in5); \ + _t0 = __lsx_vilvl_h(_s1, _s0); \ + _t1 = __lsx_vilvh_h(_s1, _s0); \ + _s0 = __lsx_vilvh_h(_in6, _in4); \ + _s1 = __lsx_vilvh_h(_in7, _in5); \ + _t2 = __lsx_vilvl_h(_s1, _s0); \ + _t3 = __lsx_vilvh_h(_s1, _s0); \ + _s0 = __lsx_vilvl_h(_in2, _in0); \ + _s1 = __lsx_vilvl_h(_in3, _in1); \ + _t4 = __lsx_vilvl_h(_s1, _s0); \ + _t5 = __lsx_vilvh_h(_s1, _s0); \ + _s0 = __lsx_vilvh_h(_in2, _in0); \ + _s1 = __lsx_vilvh_h(_in3, _in1); \ + _t6 = __lsx_vilvl_h(_s1, _s0); \ + _t7 = __lsx_vilvh_h(_s1, _s0); \ + \ + _out0 = __lsx_vpickev_d(_t0, _t4); \ + _out2 = __lsx_vpickev_d(_t1, _t5); \ + _out4 = __lsx_vpickev_d(_t2, _t6); \ + _out6 = __lsx_vpickev_d(_t3, _t7); \ + _out1 = __lsx_vpickod_d(_t0, _t4); \ + _out3 = __lsx_vpickod_d(_t1, _t5); \ + _out5 = __lsx_vpickod_d(_t2, _t6); \ + _out7 = __lsx_vpickod_d(_t3, _t7); \ +} + +/* + * ============================================================================= + * Description : Transpose input 8x4 byte block into 4x8 + * Arguments : Inputs - _in0, _in1, _in2, _in3 (input 8x4 byte block) + * Outputs - _out0, _out1, _out2, _out3 (output 4x8 byte block) + * Return Type - as per RTYPE + * Details : The rows of the matrix become columns, and the columns become rows. + * Example : LSX_TRANSPOSE8x4_B + * _in0 : 00,01,02,03,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in1 : 10,11,12,13,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in2 : 20,21,22,23,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in3 : 30,31,32,33,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in4 : 40,41,42,43,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in5 : 50,51,52,53,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in6 : 60,61,62,63,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in7 : 70,71,72,73,00,00,00,00, 00,00,00,00,00,00,00,00 + * + * _out0 : 00,10,20,30,40,50,60,70, 00,00,00,00,00,00,00,00 + * _out1 : 01,11,21,31,41,51,61,71, 00,00,00,00,00,00,00,00 + * _out2 : 02,12,22,32,42,52,62,72, 00,00,00,00,00,00,00,00 + * _out3 : 03,13,23,33,43,53,63,73, 00,00,00,00,00,00,00,00 + * ============================================================================= + */ +#define LSX_TRANSPOSE8x4_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3) \ +{ \ + __m128i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + \ + _tmp0_m = __lsx_vpackev_w(_in4, _in0); \ + _tmp1_m = __lsx_vpackev_w(_in5, _in1); \ + _tmp2_m = __lsx_vilvl_b(_tmp1_m, _tmp0_m); \ + _tmp0_m = __lsx_vpackev_w(_in6, _in2); \ + _tmp1_m = __lsx_vpackev_w(_in7, _in3); \ + \ + _tmp3_m = __lsx_vilvl_b(_tmp1_m, _tmp0_m); \ + _tmp0_m = __lsx_vilvl_h(_tmp3_m, _tmp2_m); \ + _tmp1_m = __lsx_vilvh_h(_tmp3_m, _tmp2_m); \ + \ + _out0 = __lsx_vilvl_w(_tmp1_m, _tmp0_m); \ + _out2 = __lsx_vilvh_w(_tmp1_m, _tmp0_m); \ + _out1 = __lsx_vilvh_d(_out2, _out0); \ + _out3 = __lsx_vilvh_d(_out0, _out2); \ +} + +/* + * ============================================================================= + * Description : Transpose 16x8 block with byte elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7, in8 + * in9, in10, in11, in12, in13, in14, in15 + * Outputs - out0, out1, out2, out3, out4, out5, out6, out7 + * Details : + * Example : + * 000,001,002,003,004,005,006,007 + * 008,009,010,011,012,013,014,015 + * 016,017,018,019,020,021,022,023 + * 024,025,026,027,028,029,030,031 + * 032,033,034,035,036,037,038,039 + * 040,041,042,043,044,045,046,047 000,008,...,112,120 + * 048,049,050,051,052,053,054,055 001,009,...,113,121 + * 056,057,058,059,060,061,062,063 to 002,010,...,114,122 + * 064,068,066,067,068,069,070,071 =====> 003,011,...,115,123 + * 072,073,074,075,076,077,078,079 004,012,...,116,124 + * 080,081,082,083,084,085,086,087 005,013,...,117,125 + * 088,089,090,091,092,093,094,095 006,014,...,118,126 + * 096,097,098,099,100,101,102,103 007,015,...,119,127 + * 104,105,106,107,108,109,110,111 + * 112,113,114,115,116,117,118,119 + * 120,121,122,123,124,125,126,127 + * ============================================================================= + */ +#define LSX_TRANSPOSE16x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, _in8, \ + _in9, _in10, _in11, _in12, _in13, _in14, _in15, _out0, \ + _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ +{ \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ + __m128i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + DUP4_ARG2(__lsx_vilvl_b, _in2, _in0, _in3, _in1, _in6, _in4, _in7, _in5, \ + _tmp0, _tmp1, _tmp2, _tmp3); \ + DUP4_ARG2(__lsx_vilvl_b, _in10, _in8, _in11, _in9, _in14, _in12, _in15, \ + _in13, _tmp4, _tmp5, _tmp6, _tmp7); \ + DUP2_ARG2(__lsx_vilvl_b, _tmp1, _tmp0, _tmp3, _tmp2, _t0, _t2); \ + DUP2_ARG2(__lsx_vilvh_b, _tmp1, _tmp0, _tmp3, _tmp2, _t1, _t3); \ + DUP2_ARG2(__lsx_vilvl_b, _tmp5, _tmp4, _tmp7, _tmp6, _t4, _t6); \ + DUP2_ARG2(__lsx_vilvh_b, _tmp5, _tmp4, _tmp7, _tmp6, _t5, _t7); \ + DUP2_ARG2(__lsx_vilvl_w, _t2, _t0, _t3, _t1, _tmp0, _tmp4); \ + DUP2_ARG2(__lsx_vilvh_w, _t2, _t0, _t3, _t1, _tmp2, _tmp6); \ + DUP2_ARG2(__lsx_vilvl_w, _t6, _t4, _t7, _t5, _tmp1, _tmp5); \ + DUP2_ARG2(__lsx_vilvh_w, _t6, _t4, _t7, _t5, _tmp3, _tmp7); \ + DUP2_ARG2(__lsx_vilvl_d, _tmp1, _tmp0, _tmp3, _tmp2, _out0, _out2); \ + DUP2_ARG2(__lsx_vilvh_d, _tmp1, _tmp0, _tmp3, _tmp2, _out1, _out3); \ + DUP2_ARG2(__lsx_vilvl_d, _tmp5, _tmp4, _tmp7, _tmp6, _out4, _out6); \ + DUP2_ARG2(__lsx_vilvh_d, _tmp5, _tmp4, _tmp7, _tmp6, _out5, _out7); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 4 input vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Details : Butterfly operation + * Example : + * out0 = in0 + in3; + * out1 = in1 + in2; + * out2 = in1 - in2; + * out3 = in0 - in3; + * ============================================================================= + */ +#define LSX_BUTTERFLY_4_B(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lsx_vadd_b(_in0, _in3); \ + _out1 = __lsx_vadd_b(_in1, _in2); \ + _out2 = __lsx_vsub_b(_in1, _in2); \ + _out3 = __lsx_vsub_b(_in0, _in3); \ +} +#define LSX_BUTTERFLY_4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lsx_vadd_h(_in0, _in3); \ + _out1 = __lsx_vadd_h(_in1, _in2); \ + _out2 = __lsx_vsub_h(_in1, _in2); \ + _out3 = __lsx_vsub_h(_in0, _in3); \ +} +#define LSX_BUTTERFLY_4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lsx_vadd_w(_in0, _in3); \ + _out1 = __lsx_vadd_w(_in1, _in2); \ + _out2 = __lsx_vsub_w(_in1, _in2); \ + _out3 = __lsx_vsub_w(_in0, _in3); \ +} +#define LSX_BUTTERFLY_4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lsx_vadd_d(_in0, _in3); \ + _out1 = __lsx_vadd_d(_in1, _in2); \ + _out2 = __lsx_vsub_d(_in1, _in2); \ + _out3 = __lsx_vsub_d(_in0, _in3); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 8 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3, ~ + * Outputs - _out0, _out1, _out2, _out3, ~ + * Details : Butterfly operation + * Example : + * _out0 = _in0 + _in7; + * _out1 = _in1 + _in6; + * _out2 = _in2 + _in5; + * _out3 = _in3 + _in4; + * _out4 = _in3 - _in4; + * _out5 = _in2 - _in5; + * _out6 = _in1 - _in6; + * _out7 = _in0 - _in7; + * ============================================================================= + */ +#define LSX_BUTTERFLY_8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lsx_vadd_b(_in0, _in7); \ + _out1 = __lsx_vadd_b(_in1, _in6); \ + _out2 = __lsx_vadd_b(_in2, _in5); \ + _out3 = __lsx_vadd_b(_in3, _in4); \ + _out4 = __lsx_vsub_b(_in3, _in4); \ + _out5 = __lsx_vsub_b(_in2, _in5); \ + _out6 = __lsx_vsub_b(_in1, _in6); \ + _out7 = __lsx_vsub_b(_in0, _in7); \ +} + +#define LSX_BUTTERFLY_8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lsx_vadd_h(_in0, _in7); \ + _out1 = __lsx_vadd_h(_in1, _in6); \ + _out2 = __lsx_vadd_h(_in2, _in5); \ + _out3 = __lsx_vadd_h(_in3, _in4); \ + _out4 = __lsx_vsub_h(_in3, _in4); \ + _out5 = __lsx_vsub_h(_in2, _in5); \ + _out6 = __lsx_vsub_h(_in1, _in6); \ + _out7 = __lsx_vsub_h(_in0, _in7); \ +} + +#define LSX_BUTTERFLY_8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lsx_vadd_w(_in0, _in7); \ + _out1 = __lsx_vadd_w(_in1, _in6); \ + _out2 = __lsx_vadd_w(_in2, _in5); \ + _out3 = __lsx_vadd_w(_in3, _in4); \ + _out4 = __lsx_vsub_w(_in3, _in4); \ + _out5 = __lsx_vsub_w(_in2, _in5); \ + _out6 = __lsx_vsub_w(_in1, _in6); \ + _out7 = __lsx_vsub_w(_in0, _in7); \ +} + +#define LSX_BUTTERFLY_8_D(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lsx_vadd_d(_in0, _in7); \ + _out1 = __lsx_vadd_d(_in1, _in6); \ + _out2 = __lsx_vadd_d(_in2, _in5); \ + _out3 = __lsx_vadd_d(_in3, _in4); \ + _out4 = __lsx_vsub_d(_in3, _in4); \ + _out5 = __lsx_vsub_d(_in2, _in5); \ + _out6 = __lsx_vsub_d(_in1, _in6); \ + _out7 = __lsx_vsub_d(_in0, _in7); \ +} + +#endif //LSX + +#ifdef __loongarch_asx +#include +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed halfword + * Details : Unsigned byte elements from in_h are multiplied with + * unsigned byte elements from in_l producing a result + * twice the size of input i.e. signed halfword. + * Then this multiplied results of adjacent odd-even elements + * are added to the out vector + * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2_h_bu(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_h_bu(in_h, in_l); + out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed halfword + * Details : Signed byte elements from in_h are multiplied with + * signed byte elements from in_l producing a result + * twice the size of input i.e. signed halfword. + * Then this iniplication results of adjacent odd-even elements + * are added to the out vector + * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2_h_b(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_h_b(in_h, in_l); + out = __lasx_xvmaddwod_h_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed word + * Details : Signed halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Then this multiplied results of adjacent odd-even elements + * are added to the out vector. + * Example : out = __lasx_xvdp2_w_h(in_h, in_l) + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1 + * out : 22,38,38,22, 22,38,38,22 + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2_w_h(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_w_h(in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of word vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Retrun Type - signed double + * Details : Signed word elements from in_h are multiplied with + * signed word elements from in_l producing a result + * twice the size of input i.e. signed double word. + * Then this multiplied results of adjacent odd-even elements + * are added to the out vector. + * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2_d_w(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_d_w(in_h, in_l); + out = __lasx_xvmaddwod_d_w(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed word + * Details : Unsigned halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. unsigned word. + * Multiplication result of adjacent odd-even elements + * are added to the out vector + * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2_w_hu_h(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_w_hu_h(in_h, in_l); + out = __lasx_xvmaddwod_w_hu_h(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Retrun Type - halfword + * Details : Signed byte elements from in_h are multiplied with + * signed byte elements from in_l producing a result + * twice the size of input i.e. signed halfword. + * Then this multiplied results of adjacent odd-even elements + * are added to the in_c vector. + * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2add_h_b(__m256i in_c,__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmaddwev_h_b(in_c, in_h, in_l); + out = __lasx_xvmaddwod_h_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - per RTYPE + * Details : Signed halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result of adjacent odd-even elements + * are added to the in_c vector. + * Example : out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) + * in_c : 1,2,3,4, 1,2,3,4 + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8, + * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1, + * out : 23,40,41,26, 23,40,41,26 + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2add_w_h(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmaddwev_w_h(in_c, in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed word + * Details : Unsigned halfword elements from in_h are multiplied with + * unsigned halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result of adjacent odd-even elements + * are added to the in_c vector. + * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2add_w_hu(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmaddwev_w_hu(in_c, in_h, in_l); + out = __lasx_xvmaddwod_w_hu(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed word + * Details : Unsigned halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result of adjacent odd-even elements + * are added to the in_c vector + * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2add_w_hu_h(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmaddwev_w_hu_h(in_c, in_h, in_l); + out = __lasx_xvmaddwod_w_hu_h(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Vector Unsigned Dot Product and Subtract + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed halfword + * Details : Unsigned byte elements from in_h are multiplied with + * unsigned byte elements from in_l producing a result + * twice the size of input i.e. signed halfword. + * Multiplication result of adjacent odd-even elements + * are added together and subtracted from double width elements + * in_c vector. + * Example : See out = __lasx_xvdp2sub_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2sub_h_bu(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_h_bu(in_h, in_l); + out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); + out = __lasx_xvsub_h(in_c, out); + return out; +} + +/* + * ============================================================================= + * Description : Vector Signed Dot Product and Subtract + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed word + * Details : Signed halfword elements from in_h are multiplied with + * Signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result of adjacent odd-even elements + * are added together and subtracted from double width elements + * in_c vector. + * Example : out = __lasx_xvdp2sub_w_h(in_c, in_h, in_l) + * in_c : 0,0,0,0, 0,0,0,0 + * in_h : 3,1,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1 + * in_l : 2,1,1,0, 1,0,0,0, 0,0,1,0, 1,0,0,1 + * out : -7,-3,0,0, 0,-1,0,-1 + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2sub_w_h(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_w_h(in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + out = __lasx_xvsub_w(in_c, out); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed word + * Details : Signed halfword elements from in_h are iniplied with + * signed halfword elements from in_l producing a result + * four times the size of input i.e. signed doubleword. + * Then this iniplication results of four adjacent elements + * are added together and stored to the out vector. + * Example : out = __lasx_xvdp4_d_h(in_h, in_l) + * in_h : 3,1,3,0, 0,0,0,1, 0,0,1,-1, 0,0,0,1 + * in_l : -2,1,1,0, 1,0,0,0, 0,0,1, 0, 1,0,0,1 + * out : -2,0,1,1 + * ============================================================================= + */ +static inline __m256i __lasx_xvdp4_d_h(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvmulwev_w_h(in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + out = __lasx_xvhaddw_d_w(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The high half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * higher half of the two-fold sign extension (signed byte + * to signed halfword) and stored to the out vector. + * Example : See out = __lasx_xvaddwh_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvaddwh_h_b(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvilvh_b(in_h, in_l); + out = __lasx_xvhaddw_h_b(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The high half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * higher half of the two-fold sign extension (signed halfword + * to signed word) and stored to the out vector. + * Example : out = __lasx_xvaddwh_w_h(in_h, in_l) + * in_h : 3, 0,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 1,0,1, 0, 1,0,0,1 + * out : 1,0,0,-1, 1,0,0, 2 + * ============================================================================= + */ + static inline __m256i __lasx_xvaddwh_w_h(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvilvh_h(in_h, in_l); + out = __lasx_xvhaddw_w_h(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * lower half of the two-fold sign extension (signed byte + * to signed halfword) and stored to the out vector. + * Example : See out = __lasx_xvaddwl_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvaddwl_h_b(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvilvl_b(in_h, in_l); + out = __lasx_xvhaddw_h_b(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * lower half of the two-fold sign extension (signed halfword + * to signed word) and stored to the out vector. + * Example : out = __lasx_xvaddwl_w_h(in_h, in_l) + * in_h : 3, 0,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 1,0,1, 0, 1,0,0,1 + * out : 5,-1,4,2, 1,0,2,-1 + * ============================================================================= + */ +static inline __m256i __lasx_xvaddwl_w_h(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvilvl_h(in_h, in_l); + out = __lasx_xvhaddw_w_h(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The out vector and the out vector are added after the + * lower half of the two-fold zero extension (unsigned byte + * to unsigned halfword) and stored to the out vector. + * Example : See out = __lasx_xvaddwl_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvaddwl_h_bu(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvilvl_b(in_h, in_l); + out = __lasx_xvhaddw_hu_bu(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_l vector after double zero extension (unsigned byte to + * signed halfword),added to the in_h vector. + * Example : See out = __lasx_xvaddw_w_w_h(in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvaddw_h_h_bu(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvsllwil_hu_bu(in_l, 0); + out = __lasx_xvadd_h(in_h, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_l vector after double sign extension (signed halfword to + * signed word), added to the in_h vector. + * Example : out = __lasx_xvaddw_w_w_h(in_h, in_l) + * in_h : 0, 1,0,0, -1,0,0,1, + * in_l : 2,-1,1,2, 1,0,0,0, 0,0,1,0, 1,0,0,1, + * out : 2, 0,1,2, -1,0,1,1, + * ============================================================================= + */ +static inline __m256i __lasx_xvaddw_w_w_h(__m256i in_h, __m256i in_l) +{ + __m256i out; + + out = __lasx_xvsllwil_w_h(in_l, 0); + out = __lasx_xvadd_w(in_h, out); + return out; +} + +/* + * ============================================================================= + * Description : Multiplication and addition calculation after expansion + * of the lower half of the vector. + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the lower half of the two-fold sign extension (signed halfword + * to signed word), and the result is added to the vector in_c, + * then stored to the out vector. + * Example : out = __lasx_xvmaddwl_w_h(in_c, in_h, in_l) + * in_c : 1,2,3,4, 5,6,7,8 + * in_h : 1,2,3,4, 1,2,3,4, 5,6,7,8, 5,6,7,8 + * in_l : 200, 300, 400, 500, 2000, 3000, 4000, 5000, + * -200,-300,-400,-500, -2000,-3000,-4000,-5000 + * out : 201, 602,1203,2004, -995, -1794,-2793,-3992 + * ============================================================================= + */ +static inline __m256i __lasx_xvmaddwl_w_h(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i tmp0, tmp1, out; + + tmp0 = __lasx_xvsllwil_w_h(in_h, 0); + tmp1 = __lasx_xvsllwil_w_h(in_l, 0); + tmp0 = __lasx_xvmul_w(tmp0, tmp1); + out = __lasx_xvadd_w(tmp0, in_c); + return out; +} + +/* + * ============================================================================= + * Description : Multiplication and addition calculation after expansion + * of the higher half of the vector. + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the higher half of the two-fold sign extension (signed + * halfword to signed word), and the result is added to + * the vector in_c, then stored to the out vector. + * Example : See out = __lasx_xvmaddwl_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvmaddwh_w_h(__m256i in_c, __m256i in_h, __m256i in_l) +{ + __m256i tmp0, tmp1, out; + + tmp0 = __lasx_xvilvh_h(in_h, in_h); + tmp1 = __lasx_xvilvh_h(in_l, in_l); + tmp0 = __lasx_xvmulwev_w_h(tmp0, tmp1); + out = __lasx_xvadd_w(tmp0, in_c); + return out; +} + +/* + * ============================================================================= + * Description : Multiplication calculation after expansion of the lower + * half of the vector. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the lower half of the two-fold sign extension (signed + * halfword to signed word), then stored to the out vector. + * Example : out = __lasx_xvmulwl_w_h(in_h, in_l) + * in_h : 3,-1,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 0,0,1, 0, 1,0,0,1 + * out : 6,1,3,0, 0,0,1,0 + * ============================================================================= + */ +static inline __m256i __lasx_xvmulwl_w_h(__m256i in_h, __m256i in_l) +{ + __m256i tmp0, tmp1, out; + + tmp0 = __lasx_xvsllwil_w_h(in_h, 0); + tmp1 = __lasx_xvsllwil_w_h(in_l, 0); + out = __lasx_xvmul_w(tmp0, tmp1); + return out; +} + +/* + * ============================================================================= + * Description : Multiplication calculation after expansion of the lower + * half of the vector. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the lower half of the two-fold sign extension (signed + * halfword to signed word), then stored to the out vector. + * Example : out = __lasx_xvmulwh_w_h(in_h, in_l) + * in_h : 3,-1,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 0,0,1, 0, 1,0,0,1 + * out : 0,0,0,0, 0,0,0,1 + * ============================================================================= + */ +static inline __m256i __lasx_xvmulwh_w_h(__m256i in_h, __m256i in_l) +{ + __m256i tmp0, tmp1, out; + + tmp0 = __lasx_xvilvh_h(in_h, in_h); + tmp1 = __lasx_xvilvh_h(in_l, in_l); + out = __lasx_xvmulwev_w_h(tmp0, tmp1); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added saturately after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector adds the in_l vector saturately after the lower + * half of the two-fold zero extension (unsigned byte to unsigned + * halfword) and the results are stored to the out vector. + * Example : out = __lasx_xvsaddw_hu_hu_bu(in_h, in_l) + * in_h : 2,65532,1,2, 1,0,0,0, 0,0,1,0, 1,0,0,1 + * in_l : 3,6,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1, 3,18,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1 + * out : 5,65535,4,2, 1,0,0,1, 3,18,4,0, 1,0,0,2, + * ============================================================================= + */ +static inline __m256i __lasx_xvsaddw_hu_hu_bu(__m256i in_h, __m256i in_l) +{ + __m256i tmp1, out; + __m256i zero = {0}; + + tmp1 = __lasx_xvilvl_b(zero, in_l); + out = __lasx_xvsadd_hu(in_h, tmp1); + return out; +} + +/* + * ============================================================================= + * Description : Clip all halfword elements of input vector between min & max + * out = ((in) < (min)) ? (min) : (((in) > (max)) ? (max) : (in)) + * Arguments : Inputs - in (input vector) + * - min (min threshold) + * - max (max threshold) + * Outputs - in (output vector with clipped elements) + * Return Type - signed halfword + * Example : out = __lasx_xvclip_h(in, min, max) + * in : -8,2,280,249, -8,255,280,249, 4,4,4,4, 5,5,5,5 + * min : 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 + * max : 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9 + * out : 1,2,9,9, 1,9,9,9, 4,4,4,4, 5,5,5,5 + * ============================================================================= + */ +static inline __m256i __lasx_xvclip_h(__m256i in, __m256i min, __m256i max) +{ + __m256i out; + + out = __lasx_xvmax_h(min, in); + out = __lasx_xvmin_h(max, out); + return out; +} + +/* + * ============================================================================= + * Description : Clip all signed halfword elements of input vector + * between 0 & 255 + * Arguments : Inputs - in (input vector) + * Outputs - out (output vector with clipped elements) + * Return Type - signed halfword + * Example : See out = __lasx_xvclip255_w(in) + * ============================================================================= + */ +static inline __m256i __lasx_xvclip255_h(__m256i in) +{ + __m256i out; + + out = __lasx_xvmaxi_h(in, 0); + out = __lasx_xvsat_hu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Clip all signed word elements of input vector + * between 0 & 255 + * Arguments : Inputs - in (input vector) + * Output - out (output vector with clipped elements) + * Return Type - signed word + * Example : out = __lasx_xvclip255_w(in) + * in : -8,255,280,249, -8,255,280,249 + * out : 0,255,255,249, 0,255,255,249 + * ============================================================================= + */ +static inline __m256i __lasx_xvclip255_w(__m256i in) +{ + __m256i out; + + out = __lasx_xvmaxi_w(in, 0); + out = __lasx_xvsat_wu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Indexed halfword element values are replicated to all + * elements in output vector. If 'indx < 8' use xvsplati_l_*, + * if 'indx >= 8' use xvsplati_h_*. + * Arguments : Inputs - in, idx + * Output - out + * Details : Idx element value from in vector is replicated to all + * elements in out vector. + * Valid index range for halfword operation is 0-7 + * Example : out = __lasx_xvsplati_l_h(in, idx) + * in : 20,10,11,12, 13,14,15,16, 0,0,2,0, 0,0,0,0 + * idx : 0x02 + * out : 11,11,11,11, 11,11,11,11, 11,11,11,11, 11,11,11,11 + * ============================================================================= + */ +static inline __m256i __lasx_xvsplati_l_h(__m256i in, int idx) +{ + __m256i out; + + out = __lasx_xvpermi_q(in, in, 0x02); + out = __lasx_xvreplve_h(out, idx); + return out; +} + +/* + * ============================================================================= + * Description : Indexed halfword element values are replicated to all + * elements in output vector. If 'indx < 8' use xvsplati_l_*, + * if 'indx >= 8' use xvsplati_h_*. + * Arguments : Inputs - in, idx + * Output - out + * Details : Idx element value from in vector is replicated to all + * elements in out vector. + * Valid index range for halfword operation is 0-7 + * Example : out = __lasx_xvsplati_h_h(in, idx) + * in : 20,10,11,12, 13,14,15,16, 0,2,0,0, 0,0,0,0 + * idx : 0x09 + * out : 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2 + * ============================================================================= + */ +static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) +{ + __m256i out; + + out = __lasx_xvpermi_q(in, in, 0x13); + out = __lasx_xvreplve_h(out, idx); + return out; +} + +/* + * ============================================================================= + * Description : Transpose 4x4 block with double word elements in vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3 + * Outputs - _out0, _out1, _out2, _out3 + * Example : LASX_TRANSPOSE4x4_D + * _in0 : 1,2,3,4 + * _in1 : 1,2,3,4 + * _in2 : 1,2,3,4 + * _in3 : 1,2,3,4 + * + * _out0 : 1,1,1,1 + * _out1 : 2,2,2,2 + * _out2 : 3,3,3,3 + * _out3 : 4,4,4,4 + * ============================================================================= + */ +#define LASX_TRANSPOSE4x4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + __m256i _tmp0, _tmp1, _tmp2, _tmp3; \ + _tmp0 = __lasx_xvilvl_d(_in1, _in0); \ + _tmp1 = __lasx_xvilvh_d(_in1, _in0); \ + _tmp2 = __lasx_xvilvl_d(_in3, _in2); \ + _tmp3 = __lasx_xvilvh_d(_in3, _in2); \ + _out0 = __lasx_xvpermi_q(_tmp2, _tmp0, 0x20); \ + _out2 = __lasx_xvpermi_q(_tmp2, _tmp0, 0x31); \ + _out1 = __lasx_xvpermi_q(_tmp3, _tmp1, 0x20); \ + _out3 = __lasx_xvpermi_q(_tmp3, _tmp1, 0x31); \ +} + +/* + * ============================================================================= + * Description : Transpose 8x8 block with word elements in vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7 + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + * Example : LASX_TRANSPOSE8x8_W + * _in0 : 1,2,3,4,5,6,7,8 + * _in1 : 2,2,3,4,5,6,7,8 + * _in2 : 3,2,3,4,5,6,7,8 + * _in3 : 4,2,3,4,5,6,7,8 + * _in4 : 5,2,3,4,5,6,7,8 + * _in5 : 6,2,3,4,5,6,7,8 + * _in6 : 7,2,3,4,5,6,7,8 + * _in7 : 8,2,3,4,5,6,7,8 + * + * _out0 : 1,2,3,4,5,6,7,8 + * _out1 : 2,2,2,2,2,2,2,2 + * _out2 : 3,3,3,3,3,3,3,3 + * _out3 : 4,4,4,4,4,4,4,4 + * _out4 : 5,5,5,5,5,5,5,5 + * _out5 : 6,6,6,6,6,6,6,6 + * _out6 : 7,7,7,7,7,7,7,7 + * _out7 : 8,8,8,8,8,8,8,8 + * ============================================================================= + */ +#define LASX_TRANSPOSE8x8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ +{ \ + __m256i _s0_m, _s1_m; \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + \ + _s0_m = __lasx_xvilvl_w(_in2, _in0); \ + _s1_m = __lasx_xvilvl_w(_in3, _in1); \ + _tmp0_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp1_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_w(_in2, _in0); \ + _s1_m = __lasx_xvilvh_w(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp3_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvl_w(_in6, _in4); \ + _s1_m = __lasx_xvilvl_w(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp5_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_w(_in6, _in4); \ + _s1_m = __lasx_xvilvh_w(_in7, _in5); \ + _tmp6_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp7_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _out0 = __lasx_xvpermi_q(_tmp4_m, _tmp0_m, 0x20); \ + _out1 = __lasx_xvpermi_q(_tmp5_m, _tmp1_m, 0x20); \ + _out2 = __lasx_xvpermi_q(_tmp6_m, _tmp2_m, 0x20); \ + _out3 = __lasx_xvpermi_q(_tmp7_m, _tmp3_m, 0x20); \ + _out4 = __lasx_xvpermi_q(_tmp4_m, _tmp0_m, 0x31); \ + _out5 = __lasx_xvpermi_q(_tmp5_m, _tmp1_m, 0x31); \ + _out6 = __lasx_xvpermi_q(_tmp6_m, _tmp2_m, 0x31); \ + _out7 = __lasx_xvpermi_q(_tmp7_m, _tmp3_m, 0x31); \ +} + +/* + * ============================================================================= + * Description : Transpose input 16x8 byte block + * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, + * _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15 + * (input 16x8 byte block) + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + * (output 8x16 byte block) + * Details : The rows of the matrix become columns, and the columns become rows. + * Example : See LASX_TRANSPOSE16x8_H + * ============================================================================= + */ +#define LASX_TRANSPOSE16x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ +{ \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + \ + _tmp0_m = __lasx_xvilvl_b(_in2, _in0); \ + _tmp1_m = __lasx_xvilvl_b(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_b(_in6, _in4); \ + _tmp3_m = __lasx_xvilvl_b(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_b(_in10, _in8); \ + _tmp5_m = __lasx_xvilvl_b(_in11, _in9); \ + _tmp6_m = __lasx_xvilvl_b(_in14, _in12); \ + _tmp7_m = __lasx_xvilvl_b(_in15, _in13); \ + _out0 = __lasx_xvilvl_b(_tmp1_m, _tmp0_m); \ + _out1 = __lasx_xvilvh_b(_tmp1_m, _tmp0_m); \ + _out2 = __lasx_xvilvl_b(_tmp3_m, _tmp2_m); \ + _out3 = __lasx_xvilvh_b(_tmp3_m, _tmp2_m); \ + _out4 = __lasx_xvilvl_b(_tmp5_m, _tmp4_m); \ + _out5 = __lasx_xvilvh_b(_tmp5_m, _tmp4_m); \ + _out6 = __lasx_xvilvl_b(_tmp7_m, _tmp6_m); \ + _out7 = __lasx_xvilvh_b(_tmp7_m, _tmp6_m); \ + _tmp0_m = __lasx_xvilvl_w(_out2, _out0); \ + _tmp2_m = __lasx_xvilvh_w(_out2, _out0); \ + _tmp4_m = __lasx_xvilvl_w(_out3, _out1); \ + _tmp6_m = __lasx_xvilvh_w(_out3, _out1); \ + _tmp1_m = __lasx_xvilvl_w(_out6, _out4); \ + _tmp3_m = __lasx_xvilvh_w(_out6, _out4); \ + _tmp5_m = __lasx_xvilvl_w(_out7, _out5); \ + _tmp7_m = __lasx_xvilvh_w(_out7, _out5); \ + _out0 = __lasx_xvilvl_d(_tmp1_m, _tmp0_m); \ + _out1 = __lasx_xvilvh_d(_tmp1_m, _tmp0_m); \ + _out2 = __lasx_xvilvl_d(_tmp3_m, _tmp2_m); \ + _out3 = __lasx_xvilvh_d(_tmp3_m, _tmp2_m); \ + _out4 = __lasx_xvilvl_d(_tmp5_m, _tmp4_m); \ + _out5 = __lasx_xvilvh_d(_tmp5_m, _tmp4_m); \ + _out6 = __lasx_xvilvl_d(_tmp7_m, _tmp6_m); \ + _out7 = __lasx_xvilvh_d(_tmp7_m, _tmp6_m); \ +} + +/* + * ============================================================================= + * Description : Transpose input 16x8 byte block + * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, + * _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15 + * (input 16x8 byte block) + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + * (output 8x16 byte block) + * Details : The rows of the matrix become columns, and the columns become rows. + * Example : LASX_TRANSPOSE16x8_H + * _in0 : 1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in1 : 2,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in2 : 3,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in3 : 4,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in4 : 5,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in5 : 6,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in6 : 7,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in7 : 8,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in8 : 9,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in9 : 1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in10 : 0,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in11 : 2,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in12 : 3,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in13 : 7,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in14 : 5,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in15 : 6,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * + * _out0 : 1,2,3,4,5,6,7,8,9,1,0,2,3,7,5,6 + * _out1 : 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 + * _out2 : 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 + * _out3 : 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + * _out4 : 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 + * _out5 : 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 + * _out6 : 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + * _out7 : 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + * ============================================================================= + */ +#define LASX_TRANSPOSE16x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ + { \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + __m256i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + \ + _tmp0_m = __lasx_xvilvl_h(_in2, _in0); \ + _tmp1_m = __lasx_xvilvl_h(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_h(_in6, _in4); \ + _tmp3_m = __lasx_xvilvl_h(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_h(_in10, _in8); \ + _tmp5_m = __lasx_xvilvl_h(_in11, _in9); \ + _tmp6_m = __lasx_xvilvl_h(_in14, _in12); \ + _tmp7_m = __lasx_xvilvl_h(_in15, _in13); \ + _t0 = __lasx_xvilvl_h(_tmp1_m, _tmp0_m); \ + _t1 = __lasx_xvilvh_h(_tmp1_m, _tmp0_m); \ + _t2 = __lasx_xvilvl_h(_tmp3_m, _tmp2_m); \ + _t3 = __lasx_xvilvh_h(_tmp3_m, _tmp2_m); \ + _t4 = __lasx_xvilvl_h(_tmp5_m, _tmp4_m); \ + _t5 = __lasx_xvilvh_h(_tmp5_m, _tmp4_m); \ + _t6 = __lasx_xvilvl_h(_tmp7_m, _tmp6_m); \ + _t7 = __lasx_xvilvh_h(_tmp7_m, _tmp6_m); \ + _tmp0_m = __lasx_xvilvl_d(_t2, _t0); \ + _tmp2_m = __lasx_xvilvh_d(_t2, _t0); \ + _tmp4_m = __lasx_xvilvl_d(_t3, _t1); \ + _tmp6_m = __lasx_xvilvh_d(_t3, _t1); \ + _tmp1_m = __lasx_xvilvl_d(_t6, _t4); \ + _tmp3_m = __lasx_xvilvh_d(_t6, _t4); \ + _tmp5_m = __lasx_xvilvl_d(_t7, _t5); \ + _tmp7_m = __lasx_xvilvh_d(_t7, _t5); \ + _out0 = __lasx_xvpermi_q(_tmp1_m, _tmp0_m, 0x20); \ + _out1 = __lasx_xvpermi_q(_tmp3_m, _tmp2_m, 0x20); \ + _out2 = __lasx_xvpermi_q(_tmp5_m, _tmp4_m, 0x20); \ + _out3 = __lasx_xvpermi_q(_tmp7_m, _tmp6_m, 0x20); \ + \ + _tmp0_m = __lasx_xvilvh_h(_in2, _in0); \ + _tmp1_m = __lasx_xvilvh_h(_in3, _in1); \ + _tmp2_m = __lasx_xvilvh_h(_in6, _in4); \ + _tmp3_m = __lasx_xvilvh_h(_in7, _in5); \ + _tmp4_m = __lasx_xvilvh_h(_in10, _in8); \ + _tmp5_m = __lasx_xvilvh_h(_in11, _in9); \ + _tmp6_m = __lasx_xvilvh_h(_in14, _in12); \ + _tmp7_m = __lasx_xvilvh_h(_in15, _in13); \ + _t0 = __lasx_xvilvl_h(_tmp1_m, _tmp0_m); \ + _t1 = __lasx_xvilvh_h(_tmp1_m, _tmp0_m); \ + _t2 = __lasx_xvilvl_h(_tmp3_m, _tmp2_m); \ + _t3 = __lasx_xvilvh_h(_tmp3_m, _tmp2_m); \ + _t4 = __lasx_xvilvl_h(_tmp5_m, _tmp4_m); \ + _t5 = __lasx_xvilvh_h(_tmp5_m, _tmp4_m); \ + _t6 = __lasx_xvilvl_h(_tmp7_m, _tmp6_m); \ + _t7 = __lasx_xvilvh_h(_tmp7_m, _tmp6_m); \ + _tmp0_m = __lasx_xvilvl_d(_t2, _t0); \ + _tmp2_m = __lasx_xvilvh_d(_t2, _t0); \ + _tmp4_m = __lasx_xvilvl_d(_t3, _t1); \ + _tmp6_m = __lasx_xvilvh_d(_t3, _t1); \ + _tmp1_m = __lasx_xvilvl_d(_t6, _t4); \ + _tmp3_m = __lasx_xvilvh_d(_t6, _t4); \ + _tmp5_m = __lasx_xvilvl_d(_t7, _t5); \ + _tmp7_m = __lasx_xvilvh_d(_t7, _t5); \ + _out4 = __lasx_xvpermi_q(_tmp1_m, _tmp0_m, 0x20); \ + _out5 = __lasx_xvpermi_q(_tmp3_m, _tmp2_m, 0x20); \ + _out6 = __lasx_xvpermi_q(_tmp5_m, _tmp4_m, 0x20); \ + _out7 = __lasx_xvpermi_q(_tmp7_m, _tmp6_m, 0x20); \ +} + +/* + * ============================================================================= + * Description : Transpose 4x4 block with halfword elements in vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3 + * Outputs - _out0, _out1, _out2, _out3 + * Return Type - signed halfword + * Details : The rows of the matrix become columns, and the columns become rows. + * Example : See LASX_TRANSPOSE8x8_H + * ============================================================================= + */ +#define LASX_TRANSPOSE4x4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + __m256i _s0_m, _s1_m; \ + \ + _s0_m = __lasx_xvilvl_h(_in1, _in0); \ + _s1_m = __lasx_xvilvl_h(_in3, _in2); \ + _out0 = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _out2 = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _out1 = __lasx_xvilvh_d(_out0, _out0); \ + _out3 = __lasx_xvilvh_d(_out2, _out2); \ +} + +/* + * ============================================================================= + * Description : Transpose input 8x8 byte block + * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7 + * (input 8x8 byte block) + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + * (output 8x8 byte block) + * Example : See LASX_TRANSPOSE8x8_H + * ============================================================================= + */ +#define LASX_TRANSPOSE8x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, _out0, \ + _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ +{ \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + _tmp0_m = __lasx_xvilvl_b(_in2, _in0); \ + _tmp1_m = __lasx_xvilvl_b(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_b(_in6, _in4); \ + _tmp3_m = __lasx_xvilvl_b(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_b(_tmp1_m, _tmp0_m); \ + _tmp5_m = __lasx_xvilvh_b(_tmp1_m, _tmp0_m); \ + _tmp6_m = __lasx_xvilvl_b(_tmp3_m, _tmp2_m); \ + _tmp7_m = __lasx_xvilvh_b(_tmp3_m, _tmp2_m); \ + _out0 = __lasx_xvilvl_w(_tmp6_m, _tmp4_m); \ + _out2 = __lasx_xvilvh_w(_tmp6_m, _tmp4_m); \ + _out4 = __lasx_xvilvl_w(_tmp7_m, _tmp5_m); \ + _out6 = __lasx_xvilvh_w(_tmp7_m, _tmp5_m); \ + _out1 = __lasx_xvbsrl_v(_out0, 8); \ + _out3 = __lasx_xvbsrl_v(_out2, 8); \ + _out5 = __lasx_xvbsrl_v(_out4, 8); \ + _out7 = __lasx_xvbsrl_v(_out6, 8); \ +} + +/* + * ============================================================================= + * Description : Transpose 8x8 block with halfword elements in vectors. + * Arguments : Inputs - _in0, _in1, ~ + * Outputs - _out0, _out1, ~ + * Details : The rows of the matrix become columns, and the columns become rows. + * Example : LASX_TRANSPOSE8x8_H + * _in0 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in1 : 8,2,3,4, 5,6,7,8, 8,2,3,4, 5,6,7,8 + * _in2 : 8,2,3,4, 5,6,7,8, 8,2,3,4, 5,6,7,8 + * _in3 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in4 : 9,2,3,4, 5,6,7,8, 9,2,3,4, 5,6,7,8 + * _in5 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in6 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in7 : 9,2,3,4, 5,6,7,8, 9,2,3,4, 5,6,7,8 + * + * _out0 : 1,8,8,1, 9,1,1,9, 1,8,8,1, 9,1,1,9 + * _out1 : 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2 + * _out2 : 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3 + * _out3 : 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4 + * _out4 : 5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5 + * _out5 : 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6 + * _out6 : 7,7,7,7, 7,7,7,7, 7,7,7,7, 7,7,7,7 + * _out7 : 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8 + * ============================================================================= + */ +#define LASX_TRANSPOSE8x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, _out0, \ + _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ +{ \ + __m256i _s0_m, _s1_m; \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + \ + _s0_m = __lasx_xvilvl_h(_in6, _in4); \ + _s1_m = __lasx_xvilvl_h(_in7, _in5); \ + _tmp0_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp1_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_h(_in6, _in4); \ + _s1_m = __lasx_xvilvh_h(_in7, _in5); \ + _tmp2_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp3_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + \ + _s0_m = __lasx_xvilvl_h(_in2, _in0); \ + _s1_m = __lasx_xvilvl_h(_in3, _in1); \ + _tmp4_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp5_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_h(_in2, _in0); \ + _s1_m = __lasx_xvilvh_h(_in3, _in1); \ + _tmp6_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp7_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + \ + _out0 = __lasx_xvpickev_d(_tmp0_m, _tmp4_m); \ + _out2 = __lasx_xvpickev_d(_tmp1_m, _tmp5_m); \ + _out4 = __lasx_xvpickev_d(_tmp2_m, _tmp6_m); \ + _out6 = __lasx_xvpickev_d(_tmp3_m, _tmp7_m); \ + _out1 = __lasx_xvpickod_d(_tmp0_m, _tmp4_m); \ + _out3 = __lasx_xvpickod_d(_tmp1_m, _tmp5_m); \ + _out5 = __lasx_xvpickod_d(_tmp2_m, _tmp6_m); \ + _out7 = __lasx_xvpickod_d(_tmp3_m, _tmp7_m); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 4 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3 + * Outputs - _out0, _out1, _out2, _out3 + * Details : Butterfly operation + * Example : LASX_BUTTERFLY_4 + * _out0 = _in0 + _in3; + * _out1 = _in1 + _in2; + * _out2 = _in1 - _in2; + * _out3 = _in0 - _in3; + * ============================================================================= + */ +#define LASX_BUTTERFLY_4_B(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lasx_xvadd_b(_in0, _in3); \ + _out1 = __lasx_xvadd_b(_in1, _in2); \ + _out2 = __lasx_xvsub_b(_in1, _in2); \ + _out3 = __lasx_xvsub_b(_in0, _in3); \ +} +#define LASX_BUTTERFLY_4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lasx_xvadd_h(_in0, _in3); \ + _out1 = __lasx_xvadd_h(_in1, _in2); \ + _out2 = __lasx_xvsub_h(_in1, _in2); \ + _out3 = __lasx_xvsub_h(_in0, _in3); \ +} +#define LASX_BUTTERFLY_4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lasx_xvadd_w(_in0, _in3); \ + _out1 = __lasx_xvadd_w(_in1, _in2); \ + _out2 = __lasx_xvsub_w(_in1, _in2); \ + _out3 = __lasx_xvsub_w(_in0, _in3); \ +} +#define LASX_BUTTERFLY_4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ +{ \ + _out0 = __lasx_xvadd_d(_in0, _in3); \ + _out1 = __lasx_xvadd_d(_in1, _in2); \ + _out2 = __lasx_xvsub_d(_in1, _in2); \ + _out3 = __lasx_xvsub_d(_in0, _in3); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 8 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3, ~ + * Outputs - _out0, _out1, _out2, _out3, ~ + * Details : Butterfly operation + * Example : LASX_BUTTERFLY_8 + * _out0 = _in0 + _in7; + * _out1 = _in1 + _in6; + * _out2 = _in2 + _in5; + * _out3 = _in3 + _in4; + * _out4 = _in3 - _in4; + * _out5 = _in2 - _in5; + * _out6 = _in1 - _in6; + * _out7 = _in0 - _in7; + * ============================================================================= + */ +#define LASX_BUTTERFLY_8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lasx_xvadd_b(_in0, _in7); \ + _out1 = __lasx_xvadd_b(_in1, _in6); \ + _out2 = __lasx_xvadd_b(_in2, _in5); \ + _out3 = __lasx_xvadd_b(_in3, _in4); \ + _out4 = __lasx_xvsub_b(_in3, _in4); \ + _out5 = __lasx_xvsub_b(_in2, _in5); \ + _out6 = __lasx_xvsub_b(_in1, _in6); \ + _out7 = __lasx_xvsub_b(_in0, _in7); \ +} + +#define LASX_BUTTERFLY_8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lasx_xvadd_h(_in0, _in7); \ + _out1 = __lasx_xvadd_h(_in1, _in6); \ + _out2 = __lasx_xvadd_h(_in2, _in5); \ + _out3 = __lasx_xvadd_h(_in3, _in4); \ + _out4 = __lasx_xvsub_h(_in3, _in4); \ + _out5 = __lasx_xvsub_h(_in2, _in5); \ + _out6 = __lasx_xvsub_h(_in1, _in6); \ + _out7 = __lasx_xvsub_h(_in0, _in7); \ +} + +#define LASX_BUTTERFLY_8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lasx_xvadd_w(_in0, _in7); \ + _out1 = __lasx_xvadd_w(_in1, _in6); \ + _out2 = __lasx_xvadd_w(_in2, _in5); \ + _out3 = __lasx_xvadd_w(_in3, _in4); \ + _out4 = __lasx_xvsub_w(_in3, _in4); \ + _out5 = __lasx_xvsub_w(_in2, _in5); \ + _out6 = __lasx_xvsub_w(_in1, _in6); \ + _out7 = __lasx_xvsub_w(_in0, _in7); \ +} + +#define LASX_BUTTERFLY_8_D(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ +{ \ + _out0 = __lasx_xvadd_d(_in0, _in7); \ + _out1 = __lasx_xvadd_d(_in1, _in6); \ + _out2 = __lasx_xvadd_d(_in2, _in5); \ + _out3 = __lasx_xvadd_d(_in3, _in4); \ + _out4 = __lasx_xvsub_d(_in3, _in4); \ + _out5 = __lasx_xvsub_d(_in2, _in5); \ + _out6 = __lasx_xvsub_d(_in1, _in6); \ + _out7 = __lasx_xvsub_d(_in0, _in7); \ +} + +#endif //LASX + +/* + * ============================================================================= + * Description : Print out elements in vector. + * Arguments : Inputs - RTYPE, _element_num, _in0, _enter + * Outputs - + * Details : Print out '_element_num' elements in 'RTYPE' vector '_in0', if + * '_enter' is TRUE, prefix "\nVP:" will be added first. + * Example : VECT_PRINT(v4i32,4,in0,1); // in0: 1,2,3,4 + * VP:1,2,3,4, + * ============================================================================= + */ +#define VECT_PRINT(RTYPE, element_num, in0, enter) \ +{ \ + RTYPE _tmp0 = (RTYPE)in0; \ + int _i = 0; \ + if (enter) \ + printf("\nVP:"); \ + for(_i = 0; _i < element_num; _i++) \ + printf("%d,",_tmp0[_i]); \ +} + +#endif /* LOONGSON_INTRINSICS_H */ +#endif /* AVUTIL_LOONGARCH_LOONGSON_INTRINSICS_H */ From cba7c0267dad3963ff52f146012dd99fd5b55c2c Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Wed, 15 Dec 2021 11:51:06 +0800 Subject: [PATCH 475/894] avcodec: [loongarch] Optimize h264qpel with LASX. ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:183 after :225 Change-Id: I7c7d2f34cd82ef728aab5ce8f6bfb46dd81f0da4 Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- libavcodec/h264qpel.c | 2 + libavcodec/h264qpel.h | 1 + libavcodec/loongarch/Makefile | 2 + .../loongarch/h264qpel_init_loongarch.c | 98 + libavcodec/loongarch/h264qpel_lasx.c | 2038 +++++++++++++++++ libavcodec/loongarch/h264qpel_lasx.h | 158 ++ 6 files changed, 2299 insertions(+) create mode 100644 libavcodec/loongarch/h264qpel_init_loongarch.c create mode 100644 libavcodec/loongarch/h264qpel_lasx.c create mode 100644 libavcodec/loongarch/h264qpel_lasx.h diff --git a/libavcodec/h264qpel.c b/libavcodec/h264qpel.c index 50e82e23b0..535ebd25b4 100644 --- a/libavcodec/h264qpel.c +++ b/libavcodec/h264qpel.c @@ -106,4 +106,6 @@ av_cold void ff_h264qpel_init(H264QpelContext *c, int bit_depth) ff_h264qpel_init_x86(c, bit_depth); if (ARCH_MIPS) ff_h264qpel_init_mips(c, bit_depth); + if (ARCH_LOONGARCH64) + ff_h264qpel_init_loongarch(c, bit_depth); } diff --git a/libavcodec/h264qpel.h b/libavcodec/h264qpel.h index 7c57ad001c..0259e8de23 100644 --- a/libavcodec/h264qpel.h +++ b/libavcodec/h264qpel.h @@ -36,5 +36,6 @@ void ff_h264qpel_init_arm(H264QpelContext *c, int bit_depth); void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth); void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth); void ff_h264qpel_init_mips(H264QpelContext *c, int bit_depth); +void ff_h264qpel_init_loongarch(H264QpelContext *c, int bit_depth); #endif /* AVCODEC_H264QPEL_H */ diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index f8fb54c925..4e2ce8487f 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -1,2 +1,4 @@ OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_init_loongarch.o +OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o +LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o diff --git a/libavcodec/loongarch/h264qpel_init_loongarch.c b/libavcodec/loongarch/h264qpel_init_loongarch.c new file mode 100644 index 0000000000..969c9c376c --- /dev/null +++ b/libavcodec/loongarch/h264qpel_init_loongarch.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "h264qpel_lasx.h" +#include "libavutil/attributes.h" +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/h264qpel.h" + +av_cold void ff_h264qpel_init_loongarch(H264QpelContext *c, int bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_lasx(cpu_flags)) { + if (8 == bit_depth) { + c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_lasx; + c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_lasx; + c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_lasx; + c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_lasx; + c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_lasx; + c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_lasx; + + c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_lasx; + c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_lasx; + c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_lasx; + c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_lasx; + c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_lasx; + c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_lasx; + c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_lasx; + c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_lasx; + c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_lasx; + c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_lasx; + c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_lasx; + c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_lasx; + c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_lasx; + c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_lasx; + c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_lasx; + c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_lasx; + c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_lasx; + c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_lasx; + c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_lasx; + c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_lasx; + c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_lasx; + c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_lasx; + c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_lasx; + c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_lasx; + c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_lasx; + c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_lasx; + + c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_lasx; + c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_lasx; + c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_lasx; + c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_lasx; + c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_lasx; + c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_lasx; + c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_lasx; + c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_lasx; + c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_lasx; + c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_lasx; + c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_lasx; + c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_lasx; + c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_lasx; + c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_lasx; + c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_lasx; + c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_lasx; + c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_lasx; + c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_lasx; + c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_lasx; + c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_lasx; + c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_lasx; + c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_lasx; + c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_lasx; + c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_lasx; + c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_lasx; + c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_lasx; + c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_lasx; + c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_lasx; + c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_lasx; + c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_lasx; + } + } +} diff --git a/libavcodec/loongarch/h264qpel_lasx.c b/libavcodec/loongarch/h264qpel_lasx.c new file mode 100644 index 0000000000..1c142e510e --- /dev/null +++ b/libavcodec/loongarch/h264qpel_lasx.c @@ -0,0 +1,2038 @@ +/* + * Loongson LASX optimized h264qpel + * + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "h264qpel_lasx.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "libavutil/attributes.h" + +static const uint8_t luma_mask_arr[16 * 6] __attribute__((aligned(0x40))) = { + /* 8 width cases */ + 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, + 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, + 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, + 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, + 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, + 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 +}; + +#define AVC_HORZ_FILTER_SH(in0, in1, mask0, mask1, mask2) \ +( { \ + __m256i out0_m; \ + __m256i tmp0_m; \ + \ + tmp0_m = __lasx_xvshuf_b(in1, in0, mask0); \ + out0_m = __lasx_xvhaddw_h_b(tmp0_m, tmp0_m); \ + tmp0_m = __lasx_xvshuf_b(in1, in0, mask1); \ + out0_m = __lasx_xvdp2add_h_b(out0_m, minus5b, tmp0_m); \ + tmp0_m = __lasx_xvshuf_b(in1, in0, mask2); \ + out0_m = __lasx_xvdp2add_h_b(out0_m, plus20b, tmp0_m); \ + \ + out0_m; \ +} ) + +#define AVC_DOT_SH3_SH(in0, in1, in2, coeff0, coeff1, coeff2) \ +( { \ + __m256i out0_m; \ + \ + out0_m = __lasx_xvdp2_h_b(in0, coeff0); \ + DUP2_ARG3(__lasx_xvdp2add_h_b, out0_m, in1, coeff1, out0_m,\ + in2, coeff2, out0_m, out0_m); \ + \ + out0_m; \ +} ) + +static av_always_inline +void avc_luma_hv_qrt_and_aver_dst_16x16_lasx(uint8_t *src_x, + uint8_t *src_y, + uint8_t *dst, ptrdiff_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + uint32_t loop_cnt; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tmp0, tmp1; + __m256i src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + __m256i src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + __m256i src_vt7, src_vt8; + __m256i src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h, src_vt54_h; + __m256i src_vt65_h, src_vt76_h, src_vt87_h, filt0, filt1, filt2; + __m256i hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + __m256i vt_out3, out0, out1, out2, out3; + __m256i minus5b = __lasx_xvldi(0xFB); + __m256i plus20b = __lasx_xvldi(20); + + filt0 = __lasx_xvreplgr2vr_h(filt_const0); + filt1 = __lasx_xvreplgr2vr_h(filt_const1); + filt2 = __lasx_xvreplgr2vr_h(filt_const2); + + mask0 = __lasx_xvld(luma_mask_arr, 0); + DUP2_ARG2(__lasx_xvld, luma_mask_arr, 32, luma_mask_arr, 64, mask1, mask2); + src_vt0 = __lasx_xvld(src_y, 0); + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, src_y, stride_3x, + src_y, stride_4x, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += stride_4x; + + src_vt0 = __lasx_xvxori_b(src_vt0, 128); + DUP4_ARG2(__lasx_xvxori_b, src_vt1, 128, src_vt2, 128, src_vt3, 128, + src_vt4, 128, src_vt1, src_vt2, src_vt3, src_vt4); + + for (loop_cnt = 4; loop_cnt--;) { + src_hz0 = __lasx_xvld(src_x, 0); + DUP2_ARG2(__lasx_xvldx, src_x, stride, src_x, stride_2x, + src_hz1, src_hz2); + src_hz3 = __lasx_xvldx(src_x, stride_3x); + src_x += stride_4x; + src_hz0 = __lasx_xvpermi_d(src_hz0, 0x94); + src_hz1 = __lasx_xvpermi_d(src_hz1, 0x94); + src_hz2 = __lasx_xvpermi_d(src_hz2, 0x94); + src_hz3 = __lasx_xvpermi_d(src_hz3, 0x94); + DUP4_ARG2(__lasx_xvxori_b, src_hz0, 128, src_hz1, 128, src_hz2, 128, + src_hz3, 128, src_hz0, src_hz1, src_hz2, src_hz3); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + hz_out0 = __lasx_xvssrarni_b_h(hz_out1, hz_out0, 5); + hz_out2 = __lasx_xvssrarni_b_h(hz_out3, hz_out2, 5); + + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, + src_y, stride_3x, src_y, stride_4x, + src_vt5, src_vt6, src_vt7, src_vt8); + src_y += stride_4x; + + DUP4_ARG2(__lasx_xvxori_b, src_vt5, 128, src_vt6, 128, src_vt7, 128, + src_vt8, 128, src_vt5, src_vt6, src_vt7, src_vt8); + + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_vt4, 0x02, src_vt1, src_vt5, + 0x02, src_vt2, src_vt6, 0x02, src_vt3, src_vt7, 0x02, + src_vt0, src_vt1, src_vt2, src_vt3); + src_vt87_h = __lasx_xvpermi_q(src_vt4, src_vt8, 0x02); + DUP4_ARG2(__lasx_xvilvh_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_hz0, src_hz1, src_hz2, src_hz3); + DUP4_ARG2(__lasx_xvilvl_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_vt0, src_vt1, src_vt2, src_vt3); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x02, src_vt1, src_hz1, + 0x02, src_vt2, src_hz2, 0x02, src_vt3, src_hz3, 0x02, + src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x13, src_vt1, src_hz1, + 0x13, src_vt2, src_hz2, 0x13, src_vt3, src_hz3, 0x13, + src_vt54_h, src_vt65_h, src_vt76_h, src_vt87_h); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_h, src_vt32_h, src_vt54_h, filt0, + filt1, filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_h, src_vt43_h, src_vt65_h, filt0, + filt1, filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_h, src_vt54_h, src_vt76_h, filt0, + filt1, filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_h, src_vt65_h, src_vt87_h, filt0, + filt1, filt2); + vt_out0 = __lasx_xvssrarni_b_h(vt_out1, vt_out0, 5); + vt_out2 = __lasx_xvssrarni_b_h(vt_out3, vt_out2, 5); + + DUP2_ARG2(__lasx_xvaddwl_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out0, out2); + DUP2_ARG2(__lasx_xvaddwh_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out1, out3); + tmp0 = __lasx_xvssrarni_b_h(out1, out0, 1); + tmp1 = __lasx_xvssrarni_b_h(out3, out2, 1); + + DUP2_ARG2(__lasx_xvxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + out0 = __lasx_xvld(dst, 0); + DUP2_ARG2(__lasx_xvldx, dst, stride, dst, stride_2x, out1, out2); + out3 = __lasx_xvldx(dst, stride_3x); + out0 = __lasx_xvpermi_q(out0, out2, 0x02); + out1 = __lasx_xvpermi_q(out1, out3, 0x02); + out2 = __lasx_xvilvl_d(out1, out0); + out3 = __lasx_xvilvh_d(out1, out0); + out0 = __lasx_xvpermi_q(out2, out3, 0x02); + out1 = __lasx_xvpermi_q(out2, out3, 0x13); + tmp0 = __lasx_xvavgr_bu(out0, tmp0); + tmp1 = __lasx_xvavgr_bu(out1, tmp1); + + __lasx_xvstelm_d(tmp0, dst, 0, 0); + __lasx_xvstelm_d(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 0, 0); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 0, 1); + + __lasx_xvstelm_d(tmp0, dst, 8, 2); + __lasx_xvstelm_d(tmp0, dst + stride, 8, 3); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 8, 2); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 8, 3); + + dst += stride_4x; + src_vt0 = src_vt4; + src_vt1 = src_vt5; + src_vt2 = src_vt6; + src_vt3 = src_vt7; + src_vt4 = src_vt8; + } +} + +static av_always_inline void +avc_luma_hv_qrt_16x16_lasx(uint8_t *src_x, uint8_t *src_y, + uint8_t *dst, ptrdiff_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + uint32_t loop_cnt; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tmp0, tmp1; + __m256i src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + __m256i src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + __m256i src_vt7, src_vt8; + __m256i src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h, src_vt54_h; + __m256i src_vt65_h, src_vt76_h, src_vt87_h, filt0, filt1, filt2; + __m256i hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + __m256i vt_out3, out0, out1, out2, out3; + __m256i minus5b = __lasx_xvldi(0xFB); + __m256i plus20b = __lasx_xvldi(20); + + filt0 = __lasx_xvreplgr2vr_h(filt_const0); + filt1 = __lasx_xvreplgr2vr_h(filt_const1); + filt2 = __lasx_xvreplgr2vr_h(filt_const2); + + mask0 = __lasx_xvld(luma_mask_arr, 0); + DUP2_ARG2(__lasx_xvld, luma_mask_arr, 32, luma_mask_arr, 64, mask1, mask2); + src_vt0 = __lasx_xvld(src_y, 0); + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, src_y, stride_3x, + src_y, stride_4x, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += stride_4x; + + src_vt0 = __lasx_xvxori_b(src_vt0, 128); + DUP4_ARG2(__lasx_xvxori_b, src_vt1, 128, src_vt2, 128, src_vt3, 128, + src_vt4, 128, src_vt1, src_vt2, src_vt3, src_vt4); + + for (loop_cnt = 4; loop_cnt--;) { + src_hz0 = __lasx_xvld(src_x, 0); + DUP2_ARG2(__lasx_xvldx, src_x, stride, src_x, stride_2x, + src_hz1, src_hz2); + src_hz3 = __lasx_xvldx(src_x, stride_3x); + src_x += stride_4x; + src_hz0 = __lasx_xvpermi_d(src_hz0, 0x94); + src_hz1 = __lasx_xvpermi_d(src_hz1, 0x94); + src_hz2 = __lasx_xvpermi_d(src_hz2, 0x94); + src_hz3 = __lasx_xvpermi_d(src_hz3, 0x94); + DUP4_ARG2(__lasx_xvxori_b, src_hz0, 128, src_hz1, 128, src_hz2, 128, + src_hz3, 128, src_hz0, src_hz1, src_hz2, src_hz3); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + hz_out0 = __lasx_xvssrarni_b_h(hz_out1, hz_out0, 5); + hz_out2 = __lasx_xvssrarni_b_h(hz_out3, hz_out2, 5); + + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, + src_y, stride_3x, src_y, stride_4x, + src_vt5, src_vt6, src_vt7, src_vt8); + src_y += stride_4x; + + DUP4_ARG2(__lasx_xvxori_b, src_vt5, 128, src_vt6, 128, src_vt7, 128, + src_vt8, 128, src_vt5, src_vt6, src_vt7, src_vt8); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_vt4, 0x02, src_vt1, src_vt5, + 0x02, src_vt2, src_vt6, 0x02, src_vt3, src_vt7, 0x02, + src_vt0, src_vt1, src_vt2, src_vt3); + src_vt87_h = __lasx_xvpermi_q(src_vt4, src_vt8, 0x02); + DUP4_ARG2(__lasx_xvilvh_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_hz0, src_hz1, src_hz2, src_hz3); + DUP4_ARG2(__lasx_xvilvl_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_vt0, src_vt1, src_vt2, src_vt3); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x02, src_vt1, + src_hz1, 0x02, src_vt2, src_hz2, 0x02, src_vt3, src_hz3, + 0x02, src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x13, src_vt1, + src_hz1, 0x13, src_vt2, src_hz2, 0x13, src_vt3, src_hz3, + 0x13, src_vt54_h, src_vt65_h, src_vt76_h, src_vt87_h); + + vt_out0 = AVC_DOT_SH3_SH(src_vt10_h, src_vt32_h, src_vt54_h, + filt0, filt1, filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_h, src_vt43_h, src_vt65_h, + filt0, filt1, filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_h, src_vt54_h, src_vt76_h, + filt0, filt1, filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_h, src_vt65_h, src_vt87_h, + filt0, filt1, filt2); + vt_out0 = __lasx_xvssrarni_b_h(vt_out1, vt_out0, 5); + vt_out2 = __lasx_xvssrarni_b_h(vt_out3, vt_out2, 5); + + DUP2_ARG2(__lasx_xvaddwl_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out0, out2); + DUP2_ARG2(__lasx_xvaddwh_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out1, out3); + tmp0 = __lasx_xvssrarni_b_h(out1, out0, 1); + tmp1 = __lasx_xvssrarni_b_h(out3, out2, 1); + + DUP2_ARG2(__lasx_xvxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lasx_xvstelm_d(tmp0, dst, 0, 0); + __lasx_xvstelm_d(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 0, 0); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 0, 1); + + __lasx_xvstelm_d(tmp0, dst, 8, 2); + __lasx_xvstelm_d(tmp0, dst + stride, 8, 3); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 8, 2); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 8, 3); + + dst += stride_4x; + src_vt0 = src_vt4; + src_vt1 = src_vt5; + src_vt2 = src_vt6; + src_vt3 = src_vt7; + src_vt4 = src_vt8; + } +} + +/* put_pixels8_8_inline_asm: dst = src */ +static av_always_inline void +put_pixels8_8_inline_asm(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + uint64_t tmp[8]; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride_2] \n\t" + "ldx.d %[tmp3], %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "ld.d %[tmp4], %[src], 0x0 \n\t" + "ldx.d %[tmp5], %[src], %[stride] \n\t" + "ldx.d %[tmp6], %[src], %[stride_2] \n\t" + "ldx.d %[tmp7], %[src], %[stride_3] \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride_2] \n\t" + "stx.d %[tmp3], %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "st.d %[tmp4], %[dst], 0x0 \n\t" + "stx.d %[tmp5], %[dst], %[stride] \n\t" + "stx.d %[tmp6], %[dst], %[stride_2] \n\t" + "stx.d %[tmp7], %[dst], %[stride_3] \n\t" + : [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]), + [tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]), + [tmp4]"=&r"(tmp[4]), [tmp5]"=&r"(tmp[5]), + [tmp6]"=&r"(tmp[6]), [tmp7]"=&r"(tmp[7]), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4), + [dst]"+&r"(dst), [src]"+&r"(src) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels8_8_lsx : dst = avg(src, dst) + * put_pixels8_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels8_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels8_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[stride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[stride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vstelm.d $vr0, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr1, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr2, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr3, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr4, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr5, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr6, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr7, %[dst], 0, 0 \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels8_8_lsx : dst = avg(src, dst) + * put_pixels8_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels8_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +put_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src, const uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x08 \n\t" + "vld $vr10, %[half], 0x10 \n\t" + "vld $vr11, %[half], 0x18 \n\t" + "vld $vr12, %[half], 0x20 \n\t" + "vld $vr13, %[half], 0x28 \n\t" + "vld $vr14, %[half], 0x30 \n\t" + "vld $vr15, %[half], 0x38 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vstelm.d $vr0, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr1, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr2, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr3, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr4, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr5, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr6, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr7, %[dst], 0, 0 \n\t" + : [dst]"+&r"(dst), [half]"+&r"(half), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [srcStride]"r"(srcStride), [dstStride]"r"(dstStride) + : "memory" + ); +} + +/* avg_pixels8_8_lsx : dst = avg(src, dst) + * put_pixels8_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels8_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src, const uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x08 \n\t" + "vld $vr10, %[half], 0x10 \n\t" + "vld $vr11, %[half], 0x18 \n\t" + "vld $vr12, %[half], 0x20 \n\t" + "vld $vr13, %[half], 0x28 \n\t" + "vld $vr14, %[half], 0x30 \n\t" + "vld $vr15, %[half], 0x38 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "slli.d %[stride_2], %[dstStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[dstStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[dstStride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[dstStride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vstelm.d $vr0, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr1, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr2, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr3, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr4, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr5, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr6, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr7, %[dst], 0, 0 \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [half]"+&r"(half), + [src]"+&r"(src), [stride_2]"=&r"(stride_2), + [stride_3]"=&r"(stride_3), [stride_4]"=&r"(stride_4) + : [dstStride]"r"(dstStride), [srcStride]"r"(srcStride) + : "memory" + ); +} + +/* put_pixels16_8_lsx: dst = src */ +static av_always_inline void +put_pixels16_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + : [dst]"+&r"(dst), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels16_8_lsx : dst = avg(src, dst) + * put_pixels16_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels16_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels16_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[stride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[stride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + + /* h8~h15 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[stride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[stride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels16_8_lsx : dst = avg(src, dst) + * put_pixels16_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels16_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +put_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src, uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + ptrdiff_t stride_2, stride_3, stride_4; + ptrdiff_t dstride_2, dstride_3, dstride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "slli.d %[dstride_2], %[dstStride], 1 \n\t" + "add.d %[dstride_3], %[dstride_2], %[dstStride] \n\t" + "slli.d %[dstride_4], %[dstride_2], 1 \n\t" + /* h0~h7 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x10 \n\t" + "vld $vr10, %[half], 0x20 \n\t" + "vld $vr11, %[half], 0x30 \n\t" + "vld $vr12, %[half], 0x40 \n\t" + "vld $vr13, %[half], 0x50 \n\t" + "vld $vr14, %[half], 0x60 \n\t" + "vld $vr15, %[half], 0x70 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + + /* h8~h15 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x80 \n\t" + "vld $vr9, %[half], 0x90 \n\t" + "vld $vr10, %[half], 0xa0 \n\t" + "vld $vr11, %[half], 0xb0 \n\t" + "vld $vr12, %[half], 0xc0 \n\t" + "vld $vr13, %[half], 0xd0 \n\t" + "vld $vr14, %[half], 0xe0 \n\t" + "vld $vr15, %[half], 0xf0 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + : [dst]"+&r"(dst), [half]"+&r"(half), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4), [dstride_2]"=&r"(dstride_2), + [dstride_3]"=&r"(dstride_3), [dstride_4]"=&r"(dstride_4) + : [dstStride]"r"(dstStride), [srcStride]"r"(srcStride) + : "memory" + ); +} + +/* avg_pixels16_8_lsx : dst = avg(src, dst) + * put_pixels16_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels16_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src, uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + ptrdiff_t dstride_2, dstride_3, dstride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "slli.d %[dstride_2], %[dstStride], 1 \n\t" + "add.d %[dstride_3], %[dstride_2], %[dstStride] \n\t" + "slli.d %[dstride_4], %[dstride_2], 1 \n\t" + /* h0~h7 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x10 \n\t" + "vld $vr10, %[half], 0x20 \n\t" + "vld $vr11, %[half], 0x30 \n\t" + "vld $vr12, %[half], 0x40 \n\t" + "vld $vr13, %[half], 0x50 \n\t" + "vld $vr14, %[half], 0x60 \n\t" + "vld $vr15, %[half], 0x70 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[dstStride] \n\t" + "vldx $vr10, %[tmp], %[dstride_2] \n\t" + "vldx $vr11, %[tmp], %[dstride_3] \n\t" + "add.d %[tmp], %[tmp], %[dstride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[dstStride] \n\t" + "vldx $vr14, %[tmp], %[dstride_2] \n\t" + "vldx $vr15, %[tmp], %[dstride_3] \n\t" + "add.d %[tmp], %[tmp], %[dstride_4] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + + /* h8~h15 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x80 \n\t" + "vld $vr9, %[half], 0x90 \n\t" + "vld $vr10, %[half], 0xa0 \n\t" + "vld $vr11, %[half], 0xb0 \n\t" + "vld $vr12, %[half], 0xc0 \n\t" + "vld $vr13, %[half], 0xd0 \n\t" + "vld $vr14, %[half], 0xe0 \n\t" + "vld $vr15, %[half], 0xf0 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[dstStride] \n\t" + "vldx $vr10, %[tmp], %[dstride_2] \n\t" + "vldx $vr11, %[tmp], %[dstride_3] \n\t" + "add.d %[tmp], %[tmp], %[dstride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[dstStride] \n\t" + "vldx $vr14, %[tmp], %[dstride_2] \n\t" + "vldx $vr15, %[tmp], %[dstride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [half]"+&r"(half), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4), [dstride_2]"=&r"(dstride_2), + [dstride_3]"=&r"(dstride_3), [dstride_4]"=&r"(dstride_4) + : [dstStride]"r"(dstStride), [srcStride]"r"(srcStride) + : "memory" + ); +} + +#define QPEL8_H_LOWPASS(out_v) \ + src00 = __lasx_xvld(src, - 2); \ + src += srcStride; \ + src10 = __lasx_xvld(src, - 2); \ + src += srcStride; \ + src00 = __lasx_xvpermi_q(src00, src10, 0x02); \ + src01 = __lasx_xvshuf_b(src00, src00, (__m256i)mask1); \ + src02 = __lasx_xvshuf_b(src00, src00, (__m256i)mask2); \ + src03 = __lasx_xvshuf_b(src00, src00, (__m256i)mask3); \ + src04 = __lasx_xvshuf_b(src00, src00, (__m256i)mask4); \ + src05 = __lasx_xvshuf_b(src00, src00, (__m256i)mask5); \ + DUP2_ARG2(__lasx_xvaddwl_h_bu, src02, src03, src01, src04, src02, src01);\ + src00 = __lasx_xvaddwl_h_bu(src00, src05); \ + src02 = __lasx_xvmul_h(src02, h_20); \ + src01 = __lasx_xvmul_h(src01, h_5); \ + src02 = __lasx_xvssub_h(src02, src01); \ + src02 = __lasx_xvsadd_h(src02, src00); \ + src02 = __lasx_xvsadd_h(src02, h_16); \ + out_v = __lasx_xvssrani_bu_h(src02, src02, 5); \ + +static av_always_inline void +put_h264_qpel8_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, int dstStride, + int srcStride) +{ + int dstStride_2x = dstStride << 1; + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i out0, out1, out2, out3; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + + QPEL8_H_LOWPASS(out0) + QPEL8_H_LOWPASS(out1) + QPEL8_H_LOWPASS(out2) + QPEL8_H_LOWPASS(out3) + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + dstStride, 0, 2); + dst += dstStride_2x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + dstStride, 0, 2); + dst += dstStride_2x; + __lasx_xvstelm_d(out2, dst, 0, 0); + __lasx_xvstelm_d(out2, dst + dstStride, 0, 2); + dst += dstStride_2x; + __lasx_xvstelm_d(out3, dst, 0, 0); + __lasx_xvstelm_d(out3, dst + dstStride, 0, 2); +} + +#define QPEL8_V_LOWPASS(src0, src1, src2, src3, src4, src5, src6, \ + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5) \ +{ \ + tmp0 = __lasx_xvpermi_q(src0, src1, 0x02); \ + tmp1 = __lasx_xvpermi_q(src1, src2, 0x02); \ + tmp2 = __lasx_xvpermi_q(src2, src3, 0x02); \ + tmp3 = __lasx_xvpermi_q(src3, src4, 0x02); \ + tmp4 = __lasx_xvpermi_q(src4, src5, 0x02); \ + tmp5 = __lasx_xvpermi_q(src5, src6, 0x02); \ + DUP2_ARG2(__lasx_xvaddwl_h_bu, tmp2, tmp3, tmp1, tmp4, tmp2, tmp1); \ + tmp0 = __lasx_xvaddwl_h_bu(tmp0, tmp5); \ + tmp2 = __lasx_xvmul_h(tmp2, h_20); \ + tmp1 = __lasx_xvmul_h(tmp1, h_5); \ + tmp2 = __lasx_xvssub_h(tmp2, tmp1); \ + tmp2 = __lasx_xvsadd_h(tmp2, tmp0); \ + tmp2 = __lasx_xvsadd_h(tmp2, h_16); \ + tmp2 = __lasx_xvssrani_bu_h(tmp2, tmp2, 5); \ +} + +static av_always_inline void +put_h264_qpel8_v_lowpass_lasx(uint8_t *dst, uint8_t *src, int dstStride, + int srcStride) +{ + int srcStride_2x = srcStride << 1; + int dstStride_2x = dstStride << 1; + int srcStride_4x = srcStride << 2; + int srcStride_3x = srcStride_2x + srcStride; + __m256i src00, src01, src02, src03, src04, src05, src06; + __m256i src07, src08, src09, src10, src11, src12; + __m256i tmp00, tmp01, tmp02, tmp03, tmp04, tmp05; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + + DUP2_ARG2(__lasx_xvld, src - srcStride_2x, 0, src - srcStride, 0, + src00, src01); + src02 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src03, src04, src05, src06); + src += srcStride_4x; + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src07, src08, src09, src10); + src += srcStride_4x; + DUP2_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src11, src12); + + QPEL8_V_LOWPASS(src00, src01, src02, src03, src04, src05, src06, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src02, src03, src04, src05, src06, src07, src08, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src04, src05, src06, src07, src08, src09, src10, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src06, src07, src08, src09, src10, src11, src12, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); +} + +static av_always_inline void +avg_h264_qpel8_v_lowpass_lasx(uint8_t *dst, uint8_t *src, int dstStride, + int srcStride) +{ + int srcStride_2x = srcStride << 1; + int srcStride_4x = srcStride << 2; + int dstStride_2x = dstStride << 1; + int dstStride_4x = dstStride << 2; + int srcStride_3x = srcStride_2x + srcStride; + int dstStride_3x = dstStride_2x + dstStride; + __m256i src00, src01, src02, src03, src04, src05, src06; + __m256i src07, src08, src09, src10, src11, src12, tmp00; + __m256i tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, tmp08, tmp09; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + + + DUP2_ARG2(__lasx_xvld, src - srcStride_2x, 0, src - srcStride, 0, + src00, src01); + src02 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src03, src04, src05, src06); + src += srcStride_4x; + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src07, src08, src09, src10); + src += srcStride_4x; + DUP2_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src11, src12); + + tmp06 = __lasx_xvld(dst, 0); + DUP4_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, + dst, dstStride_3x, dst, dstStride_4x, + tmp07, tmp02, tmp03, tmp04); + dst += dstStride_4x; + DUP2_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, + tmp05, tmp00); + tmp01 = __lasx_xvldx(dst, dstStride_3x); + dst -= dstStride_4x; + + tmp06 = __lasx_xvpermi_q(tmp06, tmp07, 0x02); + tmp07 = __lasx_xvpermi_q(tmp02, tmp03, 0x02); + tmp08 = __lasx_xvpermi_q(tmp04, tmp05, 0x02); + tmp09 = __lasx_xvpermi_q(tmp00, tmp01, 0x02); + + QPEL8_V_LOWPASS(src00, src01, src02, src03, src04, src05, src06, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp06 = __lasx_xvavgr_bu(tmp06, tmp02); + __lasx_xvstelm_d(tmp06, dst, 0, 0); + __lasx_xvstelm_d(tmp06, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src02, src03, src04, src05, src06, src07, src08, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp07 = __lasx_xvavgr_bu(tmp07, tmp02); + __lasx_xvstelm_d(tmp07, dst, 0, 0); + __lasx_xvstelm_d(tmp07, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src04, src05, src06, src07, src08, src09, src10, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp08 = __lasx_xvavgr_bu(tmp08, tmp02); + __lasx_xvstelm_d(tmp08, dst, 0, 0); + __lasx_xvstelm_d(tmp08, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src06, src07, src08, src09, src10, src11, src12, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp09 = __lasx_xvavgr_bu(tmp09, tmp02); + __lasx_xvstelm_d(tmp09, dst, 0, 0); + __lasx_xvstelm_d(tmp09, dst + dstStride, 0, 2); +} + +#define QPEL8_HV_LOWPASS_H(tmp) \ +{ \ + src00 = __lasx_xvld(src, -2); \ + src += srcStride; \ + src10 = __lasx_xvld(src, -2); \ + src += srcStride; \ + src00 = __lasx_xvpermi_q(src00, src10, 0x02); \ + src01 = __lasx_xvshuf_b(src00, src00, (__m256i)mask1); \ + src02 = __lasx_xvshuf_b(src00, src00, (__m256i)mask2); \ + src03 = __lasx_xvshuf_b(src00, src00, (__m256i)mask3); \ + src04 = __lasx_xvshuf_b(src00, src00, (__m256i)mask4); \ + src05 = __lasx_xvshuf_b(src00, src00, (__m256i)mask5); \ + DUP2_ARG2(__lasx_xvaddwl_h_bu, src02, src03, src01, src04, src02, src01);\ + src00 = __lasx_xvaddwl_h_bu(src00, src05); \ + src02 = __lasx_xvmul_h(src02, h_20); \ + src01 = __lasx_xvmul_h(src01, h_5); \ + src02 = __lasx_xvssub_h(src02, src01); \ + tmp = __lasx_xvsadd_h(src02, src00); \ +} + +#define QPEL8_HV_LOWPASS_V(src0, src1, src2, src3, \ + src4, src5, temp0, temp1, \ + temp2, temp3, temp4, temp5, \ + out) \ +{ \ + DUP2_ARG2(__lasx_xvaddwl_w_h, src2, src3, src1, src4, temp0, temp2); \ + DUP2_ARG2(__lasx_xvaddwh_w_h, src2, src3, src1, src4, temp1, temp3); \ + temp4 = __lasx_xvaddwl_w_h(src0, src5); \ + temp5 = __lasx_xvaddwh_w_h(src0, src5); \ + temp0 = __lasx_xvmul_w(temp0, w_20); \ + temp1 = __lasx_xvmul_w(temp1, w_20); \ + temp2 = __lasx_xvmul_w(temp2, w_5); \ + temp3 = __lasx_xvmul_w(temp3, w_5); \ + temp0 = __lasx_xvssub_w(temp0, temp2); \ + temp1 = __lasx_xvssub_w(temp1, temp3); \ + temp0 = __lasx_xvsadd_w(temp0, temp4); \ + temp1 = __lasx_xvsadd_w(temp1, temp5); \ + temp0 = __lasx_xvsadd_w(temp0, w_512); \ + temp1 = __lasx_xvsadd_w(temp1, w_512); \ + temp0 = __lasx_xvssrani_hu_w(temp0, temp0, 10); \ + temp1 = __lasx_xvssrani_hu_w(temp1, temp1, 10); \ + temp0 = __lasx_xvpackev_d(temp1, temp0); \ + out = __lasx_xvssrani_bu_h(temp0, temp0, 0); \ +} + +static av_always_inline void +put_h264_qpel8_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m256i tmp7, tmp8, tmp9, tmp10, tmp11, tmp12; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i w_20 = __lasx_xvldi(0x814); + __m256i w_5 = __lasx_xvldi(0x805); + __m256i w_512 = {512}; + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + + w_512 = __lasx_xvreplve0_w(w_512); + + src -= srcStride << 1; + QPEL8_HV_LOWPASS_H(tmp0) + QPEL8_HV_LOWPASS_H(tmp2) + QPEL8_HV_LOWPASS_H(tmp4) + QPEL8_HV_LOWPASS_H(tmp6) + QPEL8_HV_LOWPASS_H(tmp8) + QPEL8_HV_LOWPASS_H(tmp10) + QPEL8_HV_LOWPASS_H(tmp12) + tmp11 = __lasx_xvpermi_q(tmp12, tmp10, 0x21); + tmp9 = __lasx_xvpermi_q(tmp10, tmp8, 0x21); + tmp7 = __lasx_xvpermi_q(tmp8, tmp6, 0x21); + tmp5 = __lasx_xvpermi_q(tmp6, tmp4, 0x21); + tmp3 = __lasx_xvpermi_q(tmp4, tmp2, 0x21); + tmp1 = __lasx_xvpermi_q(tmp2, tmp0, 0x21); + + QPEL8_HV_LOWPASS_V(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, src00, src01, + src02, src03, src04, src05, tmp0) + QPEL8_HV_LOWPASS_V(tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, src00, src01, + src02, src03, src04, src05, tmp2) + QPEL8_HV_LOWPASS_V(tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, src00, src01, + src02, src03, src04, src05, tmp4) + QPEL8_HV_LOWPASS_V(tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, src00, src01, + src02, src03, src04, src05, tmp6) + __lasx_xvstelm_d(tmp0, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp0, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 2); +} + +static av_always_inline void +avg_h264_qpel8_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, int dstStride, + int srcStride) +{ + int dstStride_2x = dstStride << 1; + int dstStride_4x = dstStride << 2; + int dstStride_3x = dstStride_2x + dstStride; + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i dst00, dst01, dst0, dst1, dst2, dst3; + __m256i out0, out1, out2, out3; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + + QPEL8_H_LOWPASS(out0) + QPEL8_H_LOWPASS(out1) + QPEL8_H_LOWPASS(out2) + QPEL8_H_LOWPASS(out3) + src00 = __lasx_xvld(dst, 0); + DUP4_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, dst, + dstStride_3x, dst, dstStride_4x, src01, src02, src03, src04); + dst += dstStride_4x; + DUP2_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, src05, dst00); + dst01 = __lasx_xvldx(dst, dstStride_3x); + dst -= dstStride_4x; + dst0 = __lasx_xvpermi_q(src00, src01, 0x02); + dst1 = __lasx_xvpermi_q(src02, src03, 0x02); + dst2 = __lasx_xvpermi_q(src04, src05, 0x02); + dst3 = __lasx_xvpermi_q(dst00, dst01, 0x02); + dst0 = __lasx_xvavgr_bu(dst0, out0); + dst1 = __lasx_xvavgr_bu(dst1, out1); + dst2 = __lasx_xvavgr_bu(dst2, out2); + dst3 = __lasx_xvavgr_bu(dst3, out3); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + dstStride, 0, 2); + __lasx_xvstelm_d(dst1, dst + dstStride_2x, 0, 0); + __lasx_xvstelm_d(dst1, dst + dstStride_3x, 0, 2); + dst += dstStride_4x; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst + dstStride, 0, 2); + __lasx_xvstelm_d(dst3, dst + dstStride_2x, 0, 0); + __lasx_xvstelm_d(dst3, dst + dstStride_3x, 0, 2); +} + +static av_always_inline void +avg_h264_qpel8_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m256i tmp7, tmp8, tmp9, tmp10, tmp11, tmp12; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i w_20 = __lasx_xvldi(0x814); + __m256i w_5 = __lasx_xvldi(0x805); + __m256i w_512 = {512}; + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + ptrdiff_t dstStride_2x = dstStride << 1; + ptrdiff_t dstStride_4x = dstStride << 2; + ptrdiff_t dstStride_3x = dstStride_2x + dstStride; + + w_512 = __lasx_xvreplve0_w(w_512); + + src -= srcStride << 1; + QPEL8_HV_LOWPASS_H(tmp0) + QPEL8_HV_LOWPASS_H(tmp2) + QPEL8_HV_LOWPASS_H(tmp4) + QPEL8_HV_LOWPASS_H(tmp6) + QPEL8_HV_LOWPASS_H(tmp8) + QPEL8_HV_LOWPASS_H(tmp10) + QPEL8_HV_LOWPASS_H(tmp12) + tmp11 = __lasx_xvpermi_q(tmp12, tmp10, 0x21); + tmp9 = __lasx_xvpermi_q(tmp10, tmp8, 0x21); + tmp7 = __lasx_xvpermi_q(tmp8, tmp6, 0x21); + tmp5 = __lasx_xvpermi_q(tmp6, tmp4, 0x21); + tmp3 = __lasx_xvpermi_q(tmp4, tmp2, 0x21); + tmp1 = __lasx_xvpermi_q(tmp2, tmp0, 0x21); + + QPEL8_HV_LOWPASS_V(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, src00, src01, + src02, src03, src04, src05, tmp0) + QPEL8_HV_LOWPASS_V(tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, src00, src01, + src02, src03, src04, src05, tmp2) + QPEL8_HV_LOWPASS_V(tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, src00, src01, + src02, src03, src04, src05, tmp4) + QPEL8_HV_LOWPASS_V(tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, src00, src01, + src02, src03, src04, src05, tmp6) + + src00 = __lasx_xvld(dst, 0); + DUP4_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, dst, + dstStride_3x, dst, dstStride_4x, src01, src02, src03, src04); + dst += dstStride_4x; + DUP2_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, src05, tmp8); + tmp9 = __lasx_xvldx(dst, dstStride_3x); + dst -= dstStride_4x; + tmp1 = __lasx_xvpermi_q(src00, src01, 0x02); + tmp3 = __lasx_xvpermi_q(src02, src03, 0x02); + tmp5 = __lasx_xvpermi_q(src04, src05, 0x02); + tmp7 = __lasx_xvpermi_q(tmp8, tmp9, 0x02); + tmp0 = __lasx_xvavgr_bu(tmp0, tmp1); + tmp2 = __lasx_xvavgr_bu(tmp2, tmp3); + tmp4 = __lasx_xvavgr_bu(tmp4, tmp5); + tmp6 = __lasx_xvavgr_bu(tmp6, tmp7); + __lasx_xvstelm_d(tmp0, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp0, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 2); +} + +static av_always_inline void +put_h264_qpel16_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + put_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + put_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); +} + +static av_always_inline void +avg_h264_qpel16_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + avg_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + avg_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); +} + +static void put_h264_qpel16_v_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + put_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + put_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); + src += 8*srcStride; + dst += 8*dstStride; + put_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + put_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); +} + +static void avg_h264_qpel16_v_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + avg_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + avg_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); + src += 8*srcStride; + dst += 8*dstStride; + avg_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + avg_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); +} + +static void put_h264_qpel16_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + put_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + put_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); +} + +static void avg_h264_qpel16_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + avg_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + avg_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); +} + +void ff_put_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_put_pixels8_8_mmi + * which implemented in hpeldsp_mmi.c */ + put_pixels8_8_inline_asm(dst, src, stride); +} + +void ff_put_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + /* in qpel8, the stride of half and height of block is 8 */ + put_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + put_pixels8_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_put_h264_qpel8_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_v_lowpass_lasx(half, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, stride, stride); +} + +void ff_put_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_v_lowpass_lasx(half, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, src + stride, half, stride, stride); +} + +void ff_put_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_avg_pixels8_8_mmi + * which implemented in hpeldsp_mmi.c */ + avg_pixels8_8_lsx(dst, src, stride); +} + +void ff_avg_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_avg_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, stride, stride); +} + +void ff_avg_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_put_pixels16_8_mmi + * which implemented in hpeldsp_mmi.c */ + put_pixels16_8_lsx(dst, src, stride); +} + +void ff_put_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_put_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src - 2, (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_put_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src - 2, (uint8_t*)src - (stride * 2) + 1, + dst, stride); +} + +void ff_put_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_v_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src + 1, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src+stride, half, stride, stride); +} + +void ff_put_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src + stride - 2, (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_put_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src + stride, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src + stride - 2, + (uint8_t*)src - (stride * 2) + 1, dst, stride); +} + +void ff_avg_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_avg_pixels16_8_mmi + * which implemented in hpeldsp_mmi.c */ + avg_pixels16_8_lsx(dst, src, stride); +} + +void ff_avg_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src - 2, + (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_avg_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src - 2, + (uint8_t*)src - (stride * 2) + 1, + dst, stride); +} + +void ff_avg_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_v_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src + 1, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src + stride, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src + stride - 2, + (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_avg_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src + stride, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src + stride - 2, + (uint8_t*)src - (stride * 2) + 1, + dst, stride); +} diff --git a/libavcodec/loongarch/h264qpel_lasx.h b/libavcodec/loongarch/h264qpel_lasx.h new file mode 100644 index 0000000000..32b6b50917 --- /dev/null +++ b/libavcodec/loongarch/h264qpel_lasx.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_H264QPEL_LASX_H +#define AVCODEC_LOONGARCH_H264QPEL_LASX_H + +#include +#include +#include "libavcodec/h264.h" + +void ff_h264_h_lpf_luma_inter_lasx(uint8_t *src, int stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_luma_inter_lasx(uint8_t *src, int stride, + int alpha, int beta, int8_t *tc0); +void ff_put_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); + +void ff_put_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +#endif // #ifndef AVCODEC_LOONGARCH_H264QPEL_LASX_H From 3f294ec8799390af0bfc6916c312e5b1e0035c10 Mon Sep 17 00:00:00 2001 From: gxw Date: Wed, 15 Dec 2021 11:51:07 +0800 Subject: [PATCH 476/894] avcodec: [loongarch] Optimize h264dsp with LASX. ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:225 after :282 Change-Id: Ibe245827dcdfe8fc1541c6b172483151bfa9e642 Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- libavcodec/h264dsp.c | 1 + libavcodec/h264dsp.h | 2 + libavcodec/loongarch/Makefile | 2 + libavcodec/loongarch/h264dsp_init_loongarch.c | 58 + libavcodec/loongarch/h264dsp_lasx.c | 2114 +++++++++++++++++ libavcodec/loongarch/h264dsp_lasx.h | 68 + 6 files changed, 2245 insertions(+) create mode 100644 libavcodec/loongarch/h264dsp_init_loongarch.c create mode 100644 libavcodec/loongarch/h264dsp_lasx.c create mode 100644 libavcodec/loongarch/h264dsp_lasx.h diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c index e76932b565..f97ac2823c 100644 --- a/libavcodec/h264dsp.c +++ b/libavcodec/h264dsp.c @@ -157,4 +157,5 @@ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, if (ARCH_PPC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc); if (ARCH_X86) ff_h264dsp_init_x86(c, bit_depth, chroma_format_idc); if (ARCH_MIPS) ff_h264dsp_init_mips(c, bit_depth, chroma_format_idc); + if (ARCH_LOONGARCH) ff_h264dsp_init_loongarch(c, bit_depth, chroma_format_idc); } diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h index 850d4471fd..e0880c4d88 100644 --- a/libavcodec/h264dsp.h +++ b/libavcodec/h264dsp.h @@ -129,5 +129,7 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); void ff_h264dsp_init_mips(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); +void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc); #endif /* AVCODEC_H264DSP_H */ diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 4e2ce8487f..df43151dbd 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -1,4 +1,6 @@ OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_init_loongarch.o OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o +OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o +LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c new file mode 100644 index 0000000000..ddc0877a74 --- /dev/null +++ b/libavcodec/loongarch/h264dsp_init_loongarch.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Xiwei Gu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/cpu.h" +#include "h264dsp_lasx.h" + +av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + if (bit_depth == 8) { + c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_lasx; + c->h264_add_pixels8_clear = ff_h264_add_pixels8_8_lasx; + c->h264_v_loop_filter_luma = ff_h264_v_lpf_luma_8_lasx; + c->h264_h_loop_filter_luma = ff_h264_h_lpf_luma_8_lasx; + c->h264_v_loop_filter_luma_intra = ff_h264_v_lpf_luma_intra_8_lasx; + c->h264_h_loop_filter_luma_intra = ff_h264_h_lpf_luma_intra_8_lasx; + c->h264_v_loop_filter_chroma = ff_h264_v_lpf_chroma_8_lasx; + + if (chroma_format_idc <= 1) + c->h264_h_loop_filter_chroma = ff_h264_h_lpf_chroma_8_lasx; + c->h264_v_loop_filter_chroma_intra = ff_h264_v_lpf_chroma_intra_8_lasx; + + if (chroma_format_idc <= 1) + c->h264_h_loop_filter_chroma_intra = ff_h264_h_lpf_chroma_intra_8_lasx; + + /* Weighted MC */ + c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels16_8_lasx; + c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels8_8_lasx; + c->weight_h264_pixels_tab[2] = ff_weight_h264_pixels4_8_lasx; + + c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_8_lasx; + c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_8_lasx; + c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels4_8_lasx; + } + } +} diff --git a/libavcodec/loongarch/h264dsp_lasx.c b/libavcodec/loongarch/h264dsp_lasx.c new file mode 100644 index 0000000000..7fd4cedf7e --- /dev/null +++ b/libavcodec/loongarch/h264dsp_lasx.c @@ -0,0 +1,2114 @@ +/* + * Loongson LASX optimized h264dsp + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Xiwei Gu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "h264dsp_lasx.h" + +#define AVC_LPF_P1_OR_Q1(p0_or_q0_org_in, q0_or_p0_org_in, \ + p1_or_q1_org_in, p2_or_q2_org_in, \ + neg_tc_in, tc_in, p1_or_q1_out) \ +{ \ + __m256i clip3, temp; \ + \ + clip3 = __lasx_xvavgr_hu(p0_or_q0_org_in, \ + q0_or_p0_org_in); \ + temp = __lasx_xvslli_h(p1_or_q1_org_in, 1); \ + clip3 = __lasx_xvsub_h(clip3, temp); \ + clip3 = __lasx_xvavg_h(p2_or_q2_org_in, clip3); \ + clip3 = __lasx_xvclip_h(clip3, neg_tc_in, tc_in); \ + p1_or_q1_out = __lasx_xvadd_h(p1_or_q1_org_in, clip3); \ +} + +#define AVC_LPF_P0Q0(q0_or_p0_org_in, p0_or_q0_org_in, \ + p1_or_q1_org_in, q1_or_p1_org_in, \ + neg_threshold_in, threshold_in, \ + p0_or_q0_out, q0_or_p0_out) \ +{ \ + __m256i q0_sub_p0, p1_sub_q1, delta; \ + \ + q0_sub_p0 = __lasx_xvsub_h(q0_or_p0_org_in, \ + p0_or_q0_org_in); \ + p1_sub_q1 = __lasx_xvsub_h(p1_or_q1_org_in, \ + q1_or_p1_org_in); \ + q0_sub_p0 = __lasx_xvslli_h(q0_sub_p0, 2); \ + p1_sub_q1 = __lasx_xvaddi_hu(p1_sub_q1, 4); \ + delta = __lasx_xvadd_h(q0_sub_p0, p1_sub_q1); \ + delta = __lasx_xvsrai_h(delta, 3); \ + delta = __lasx_xvclip_h(delta, neg_threshold_in, \ + threshold_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_org_in, delta); \ + q0_or_p0_out = __lasx_xvsub_h(q0_or_p0_org_in, delta); \ + \ + p0_or_q0_out = __lasx_xvclip255_h(p0_or_q0_out); \ + q0_or_p0_out = __lasx_xvclip255_h(q0_or_p0_out); \ +} + +void ff_h264_h_lpf_luma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_8x = img_width << 3; + ptrdiff_t img_width_3x = img_width_2x + img_width; + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0101010100000000, 0x0303030302020202, + 0x0101010100000000, 0x0303030302020202}; + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + + if (__lasx_xbnz_v(bs_vec)) { + uint8_t *src = data - 4; + __m256i p3_org, p2_org, p1_org, p0_org, q0_org, q1_org, q2_org, q3_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i is_bs_greater_than0; + __m256i zero = __lasx_xvldi(0); + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + + { + uint8_t *src_tmp = src + img_width_8x; + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i row8, row9, row10, row11, row12, row13, row14, row15; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row4, row5, row6, row7); + src -= img_width_4x; + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, img_width, src_tmp, + img_width_2x, src_tmp, img_width_3x, + row8, row9, row10, row11); + src_tmp += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, img_width, src_tmp, + img_width_2x, src_tmp, img_width_3x, + row12, row13, row14, row15); + src_tmp -= img_width_4x; + + LASX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, + row7, row8, row9, row10, row11, + row12, row13, row14, row15, + p3_org, p2_org, p1_org, p0_org, + q0_org, q1_org, q2_org, q3_org); + } + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i neg_tc_h, tc_h, p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i p2_asub_p0, q2_asub_q0; + + neg_tc_h = __lasx_xvneg_b(tc_vec); + neg_tc_h = __lasx_vext2xv_h_b(neg_tc_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p2_org_h, p1_h; + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, p1_org_h, p2_org_h, + neg_tc_h, tc_h, p1_h); + p1_h = __lasx_xvpickev_b(p1_h, p1_h); + p1_h = __lasx_xvpermi_d(p1_h, 0xd8); + p1_org = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + } + + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q2_org_h, q1_h; + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, q1_org_h, q2_org_h, + neg_tc_h, tc_h, q1_h); + q1_h = __lasx_xvpickev_b(q1_h, q1_h); + q1_h = __lasx_xvpermi_d(q1_h, 0xd8); + q1_org = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + } + + { + __m256i neg_thresh_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + } + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i control = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + + DUP4_ARG3(__lasx_xvpermi_q, p0_org, q3_org, 0x02, p1_org, + q2_org, 0x02, p2_org, q1_org, 0x02, p3_org, + q0_org, 0x02, p0_org, p1_org, p2_org, p3_org); + DUP2_ARG2(__lasx_xvilvl_b, p1_org, p3_org, p0_org, p2_org, + row0, row2); + DUP2_ARG2(__lasx_xvilvh_b, p1_org, p3_org, p0_org, p2_org, + row1, row3); + DUP2_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row4, row6); + DUP2_ARG2(__lasx_xvilvh_b, row2, row0, row3, row1, row5, row7); + DUP4_ARG2(__lasx_xvperm_w, row4, control, row5, control, row6, + control, row7, control, row4, row5, row6, row7); + __lasx_xvstelm_d(row4, src, 0, 0); + __lasx_xvstelm_d(row4, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row4, src, 0, 2); + __lasx_xvstelm_d(row4, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 0); + __lasx_xvstelm_d(row5, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 2); + __lasx_xvstelm_d(row5, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 0); + __lasx_xvstelm_d(row6, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 2); + __lasx_xvstelm_d(row6, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 0); + __lasx_xvstelm_d(row7, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 2); + __lasx_xvstelm_d(row7, src + img_width, 0, 3); + } + } + } +} + +void ff_h264_v_lpf_luma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_3x = img_width + img_width_2x; + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0101010100000000, 0x0303030302020202, + 0x0101010100000000, 0x0303030302020202}; + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + + if (__lasx_xbnz_v(bs_vec)) { + __m256i p2_org, p1_org, p0_org, q0_org, q1_org, q2_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i is_bs_greater_than0; + __m256i zero = __lasx_xvldi(0); + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + DUP2_ARG2(__lasx_xvldx, data, -img_width_3x, data, -img_width_2x, + p2_org, p1_org); + p0_org = __lasx_xvldx(data, -img_width); + DUP2_ARG2(__lasx_xvldx, data, 0, data, img_width, q0_org, q1_org); + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i neg_tc_h, tc_h, p2_asub_p0, q2_asub_q0; + + q2_org = __lasx_xvldx(data, img_width_2x); + + neg_tc_h = __lasx_xvneg_b(tc_vec); + neg_tc_h = __lasx_vext2xv_h_b(neg_tc_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p1_h, p2_org_h; + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, p1_org_h, p2_org_h, + neg_tc_h, tc_h, p1_h); + p1_h = __lasx_xvpickev_b(p1_h, p1_h); + p1_h = __lasx_xvpermi_d(p1_h, 0xd8); + p1_h = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + p1_org = __lasx_xvpermi_q(p1_org, p1_h, 0x30); + __lasx_xvst(p1_org, data - img_width_2x, 0); + + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + } + + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q1_h, q2_org_h; + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, q1_org_h, q2_org_h, + neg_tc_h, tc_h, q1_h); + q1_h = __lasx_xvpickev_b(q1_h, q1_h); + q1_h = __lasx_xvpermi_d(q1_h, 0xd8); + q1_h = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + q1_org = __lasx_xvpermi_q(q1_org, q1_h, 0x30); + __lasx_xvst(q1_org, data + img_width, 0); + + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + + } + + { + __m256i neg_thresh_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0Xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_h = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_h = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + p0_org = __lasx_xvpermi_q(p0_org, p0_h, 0x30); + q0_org = __lasx_xvpermi_q(q0_org, q0_h, 0x30); + __lasx_xvst(p0_org, data - img_width, 0); + __lasx_xvst(q0_org, data, 0); + } + } + } +} + +void ff_h264_h_lpf_chroma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0303020201010000, 0x0303020201010000, 0x0, 0x0}; + __m256i zero = __lasx_xvldi(0); + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_3x = img_width_2x + img_width; + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + bs_vec = __lasx_xvpermi_q(zero, bs_vec, 0x30); + + if (__lasx_xbnz_v(bs_vec)) { + uint8_t *src = data - 2; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i is_bs_greater_than0; + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row4, row5, row6, row7); + src -= img_width_4x; + /* LASX_TRANSPOSE8x4_B */ + DUP4_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row6, row4, + row7, row5, p1_org, p0_org, q0_org, q1_org); + row0 = __lasx_xvilvl_b(p0_org, p1_org); + row1 = __lasx_xvilvl_b(q1_org, q0_org); + row3 = __lasx_xvilvh_w(row1, row0); + row2 = __lasx_xvilvl_w(row1, row0); + p1_org = __lasx_xvpermi_d(row2, 0x00); + p0_org = __lasx_xvpermi_d(row2, 0x55); + q0_org = __lasx_xvpermi_d(row3, 0x00); + q1_org = __lasx_xvpermi_d(row3, 0x55); + } + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + { + __m256i tc_h, neg_thresh_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + } + + p0_org = __lasx_xvilvl_b(q0_org, p0_org); + src = data - 1; + __lasx_xvstelm_h(p0_org, src, 0, 0); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 1); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 2); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 3); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 4); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 5); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 6); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 7); + } + } +} + +void ff_h264_v_lpf_chroma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + int img_width_2x = img_width << 1; + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0303020201010000, 0x0303020201010000, 0x0, 0x0}; + __m256i zero = __lasx_xvldi(0); + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + bs_vec = __lasx_xvpermi_q(zero, bs_vec, 0x30); + + if (__lasx_xbnz_v(bs_vec)) { + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i is_bs_greater_than0; + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + DUP2_ARG2(__lasx_xvldx, data, -img_width_2x, data, -img_width, + p1_org, p0_org); + DUP2_ARG2(__lasx_xvldx, data, 0, data, img_width, q0_org, q1_org); + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + { + __m256i neg_thresh_h, tc_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_h = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_h = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + __lasx_xvstelm_d(p0_h, data - img_width, 0, 0); + __lasx_xvstelm_d(q0_h, data, 0, 0); + } + } + } +} + +#define AVC_LPF_P0P1P2_OR_Q0Q1Q2(p3_or_q3_org_in, p0_or_q0_org_in, \ + q3_or_p3_org_in, p1_or_q1_org_in, \ + p2_or_q2_org_in, q1_or_p1_org_in, \ + p0_or_q0_out, p1_or_q1_out, p2_or_q2_out) \ +{ \ + __m256i threshold; \ + __m256i const2, const3 = __lasx_xvldi(0); \ + \ + const2 = __lasx_xvaddi_hu(const3, 2); \ + const3 = __lasx_xvaddi_hu(const3, 3); \ + threshold = __lasx_xvadd_h(p0_or_q0_org_in, q3_or_p3_org_in); \ + threshold = __lasx_xvadd_h(p1_or_q1_org_in, threshold); \ + \ + p0_or_q0_out = __lasx_xvslli_h(threshold, 1); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, p2_or_q2_org_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, q1_or_p1_org_in); \ + p0_or_q0_out = __lasx_xvsrar_h(p0_or_q0_out, const3); \ + \ + p1_or_q1_out = __lasx_xvadd_h(p2_or_q2_org_in, threshold); \ + p1_or_q1_out = __lasx_xvsrar_h(p1_or_q1_out, const2); \ + \ + p2_or_q2_out = __lasx_xvmul_h(p2_or_q2_org_in, const3); \ + p2_or_q2_out = __lasx_xvadd_h(p2_or_q2_out, p3_or_q3_org_in); \ + p2_or_q2_out = __lasx_xvadd_h(p2_or_q2_out, p3_or_q3_org_in); \ + p2_or_q2_out = __lasx_xvadd_h(p2_or_q2_out, threshold); \ + p2_or_q2_out = __lasx_xvsrar_h(p2_or_q2_out, const3); \ +} + +/* data[-u32_img_width] = (uint8_t)((2 * p1 + p0 + q1 + 2) >> 2); */ +#define AVC_LPF_P0_OR_Q0(p0_or_q0_org_in, q1_or_p1_org_in, \ + p1_or_q1_org_in, p0_or_q0_out) \ +{ \ + __m256i const2 = __lasx_xvldi(0); \ + const2 = __lasx_xvaddi_hu(const2, 2); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_org_in, q1_or_p1_org_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, p1_or_q1_org_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, p1_or_q1_org_in); \ + p0_or_q0_out = __lasx_xvsrar_h(p0_or_q0_out, const2); \ +} + +void ff_h264_h_lpf_luma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_3x = img_width_2x + img_width; + uint8_t *src = data - 4; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i p3_org, p2_org, p1_org, p0_org, q0_org, q1_org, q2_org, q3_org; + __m256i zero = __lasx_xvldi(0); + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i row8, row9, row10, row11, row12, row13, row14, row15; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row4, row5, row6, row7); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row8, row9, row10, row11); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row12, row13, row14, row15); + src += img_width_4x; + + LASX_TRANSPOSE16x8_B(row0, row1, row2, row3, + row4, row5, row6, row7, + row8, row9, row10, row11, + row12, row13, row14, row15, + p3_org, p2_org, p1_org, p0_org, + q0_org, q1_org, q2_org, q3_org); + } + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_beta & is_less_than_alpha; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = __lasx_xvpermi_q(zero, is_less_than, 0x30); + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p2_asub_p0, q2_asub_q0, p0_h, q0_h, negate_is_less_than_beta; + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i less_alpha_shift2_add2 = __lasx_xvsrli_b(alpha, 2); + + less_alpha_shift2_add2 = __lasx_xvaddi_bu(less_alpha_shift2_add2, 2); + less_alpha_shift2_add2 = __lasx_xvslt_bu(p0_asub_q0, + less_alpha_shift2_add2); + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p2_org_h, p3_org_h, p1_h, p2_h; + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + p3_org_h = __lasx_vext2xv_hu_bu(p3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(p3_org_h, p0_org_h, q0_org_h, p1_org_h, + p2_org_h, q1_org_h, p0_h, p1_h, p2_h); + + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, p1_h, p1_h, p2_h, p2_h, p1_h, p2_h); + DUP2_ARG2(__lasx_xvpermi_d, p1_h, 0xd8, p2_h, 0xd8, p1_h, p2_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than_beta); + p1_org = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + p2_org = __lasx_xvbitsel_v(p2_org, p2_h, is_less_than_beta); + } + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + /* combine */ + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, negate_is_less_than_beta); + + /* if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta_in) */ + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q2_org_h, q3_org_h, q1_h, q2_h; + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + q3_org_h = __lasx_vext2xv_hu_bu(q3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(q3_org_h, q0_org_h, p0_org_h, q1_org_h, + q2_org_h, p1_org_h, q0_h, q1_h, q2_h); + + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, q1_h, q1_h, q2_h, q2_h, q1_h, q2_h); + DUP2_ARG2(__lasx_xvpermi_d, q1_h, 0xd8, q2_h, 0xd8, q1_h, q2_h); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than_beta); + q1_org = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + q2_org = __lasx_xvbitsel_v(q2_org, q2_h, is_less_than_beta); + + } + + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + + /* combine */ + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, negate_is_less_than_beta); + + /* transpose and store */ + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i control = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + + DUP4_ARG3(__lasx_xvpermi_q, p0_org, q3_org, 0x02, p1_org, q2_org, + 0x02, p2_org, q1_org, 0x02, p3_org, q0_org, 0x02, + p0_org, p1_org, p2_org, p3_org); + DUP2_ARG2(__lasx_xvilvl_b, p1_org, p3_org, p0_org, p2_org, + row0, row2); + DUP2_ARG2(__lasx_xvilvh_b, p1_org, p3_org, p0_org, p2_org, + row1, row3); + DUP2_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row4, row6); + DUP2_ARG2(__lasx_xvilvh_b, row2, row0, row3, row1, row5, row7); + DUP4_ARG2(__lasx_xvperm_w, row4, control, row5, control, row6, + control, row7, control, row4, row5, row6, row7); + src = data - 4; + __lasx_xvstelm_d(row4, src, 0, 0); + __lasx_xvstelm_d(row4, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row4, src, 0, 2); + __lasx_xvstelm_d(row4, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 0); + __lasx_xvstelm_d(row5, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 2); + __lasx_xvstelm_d(row5, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 0); + __lasx_xvstelm_d(row6, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 2); + __lasx_xvstelm_d(row6, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 0); + __lasx_xvstelm_d(row7, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 2); + __lasx_xvstelm_d(row7, src + img_width, 0, 3); + } + } +} + +void ff_h264_v_lpf_luma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_3x = img_width_2x + img_width; + uint8_t *src = data - img_width_2x; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i zero = __lasx_xvldi(0); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, p1_org, p0_org, q0_org, q1_org); + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_beta & is_less_than_alpha; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = __lasx_xvpermi_q(zero, is_less_than, 0x30); + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p2_asub_p0, q2_asub_q0, p0_h, q0_h, negate_is_less_than_beta; + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i p2_org = __lasx_xvldx(src, -img_width); + __m256i q2_org = __lasx_xvldx(data, img_width_2x); + __m256i less_alpha_shift2_add2 = __lasx_xvsrli_b(alpha, 2); + less_alpha_shift2_add2 = __lasx_xvaddi_bu(less_alpha_shift2_add2, 2); + less_alpha_shift2_add2 = __lasx_xvslt_bu(p0_asub_q0, + less_alpha_shift2_add2); + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p2_org_h, p3_org_h, p1_h, p2_h; + __m256i p3_org = __lasx_xvldx(src, -img_width_2x); + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + p3_org_h = __lasx_vext2xv_hu_bu(p3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(p3_org_h, p0_org_h, q0_org_h, p1_org_h, + p2_org_h, q1_org_h, p0_h, p1_h, p2_h); + + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, p1_h, p1_h, p2_h, p2_h, p1_h, p2_h); + DUP2_ARG2(__lasx_xvpermi_d, p1_h, 0xd8, p2_h, 0xd8, p1_h, p2_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than_beta); + p1_org = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + p2_org = __lasx_xvbitsel_v(p2_org, p2_h, is_less_than_beta); + + __lasx_xvst(p1_org, src, 0); + __lasx_xvst(p2_org, src - img_width, 0); + } + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + /* combine */ + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, negate_is_less_than_beta); + __lasx_xvst(p0_org, data - img_width, 0); + + /* if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta_in) */ + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q2_org_h, q3_org_h, q1_h, q2_h; + __m256i q3_org = __lasx_xvldx(data, img_width_2x + img_width); + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + q3_org_h = __lasx_vext2xv_hu_bu(q3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(q3_org_h, q0_org_h, p0_org_h, q1_org_h, + q2_org_h, p1_org_h, q0_h, q1_h, q2_h); + + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, q1_h, q1_h, q2_h, q2_h, q1_h, q2_h); + DUP2_ARG2(__lasx_xvpermi_d, q1_h, 0xd8, q2_h, 0xd8, q1_h, q2_h); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than_beta); + q1_org = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + q2_org = __lasx_xvbitsel_v(q2_org, q2_h, is_less_than_beta); + + __lasx_xvst(q1_org, data + img_width, 0); + __lasx_xvst(q2_org, data + img_width_2x, 0); + } + + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + + /* combine */ + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, negate_is_less_than_beta); + + __lasx_xvst(q0_org, data, 0); + } +} + +void ff_h264_h_lpf_chroma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + uint8_t *src = data - 2; + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_3x = img_width_2x + img_width; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, src, + img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, src, + img_width_3x, row4, row5, row6, row7); + + /* LASX_TRANSPOSE8x4_B */ + DUP4_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row6, row4, row7, row5, + p1_org, p0_org, q0_org, q1_org); + row0 = __lasx_xvilvl_b(p0_org, p1_org); + row1 = __lasx_xvilvl_b(q1_org, q0_org); + row3 = __lasx_xvilvh_w(row1, row0); + row2 = __lasx_xvilvl_w(row1, row0); + p1_org = __lasx_xvpermi_d(row2, 0x00); + p0_org = __lasx_xvpermi_d(row2, 0x55); + q0_org = __lasx_xvpermi_d(row3, 0x00); + q1_org = __lasx_xvpermi_d(row3, 0x55); + } + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p0_h, q0_h, p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, p0_h, q0_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + } + p0_org = __lasx_xvilvl_b(q0_org, p0_org); + src = data - 1; + __lasx_xvstelm_h(p0_org, src, 0, 0); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 1); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 2); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 3); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 4); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 5); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 6); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 7); +} + +void ff_h264_v_lpf_chroma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + ptrdiff_t img_width_2x = img_width << 1; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + p1_org = __lasx_xvldx(data, -img_width_2x); + p0_org = __lasx_xvldx(data, -img_width); + DUP2_ARG2(__lasx_xvldx, data, 0, data, img_width, q0_org, q1_org); + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p0_h, q0_h, p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, p0_h, q0_h); + p0_h = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_h = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + __lasx_xvstelm_d(p0_h, data - img_width, 0, 0); + __lasx_xvstelm_d(q0_h, data, 0, 0); + } +} + +void ff_biweight_h264_pixels16_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset_in) +{ + __m256i wgt; + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3; + __m256i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i denom, offset; + int stride_2x = stride << 1; + int stride_4x = stride << 2; + int stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src += stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, tmp4, + 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp4, tmp5, tmp6, tmp7); + dst -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, tmp4, + 0x20, tmp7, tmp6, 0x20, dst0, dst1, dst2, dst3); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, 128, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec0, vec2, vec4, vec6); + DUP4_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec1, vec3, vec5, vec7); + + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec4, offset, wgt, vec5, + offset, wgt, vec6, offset, wgt, vec7, tmp4, tmp5, tmp6, tmp7); + + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + tmp4 = __lasx_xvsra_h(tmp4, denom); + tmp5 = __lasx_xvsra_h(tmp5, denom); + tmp6 = __lasx_xvsra_h(tmp6, denom); + tmp7 = __lasx_xvsra_h(tmp7, denom); + + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_xvclip255_h, tmp4, tmp5, tmp6, tmp7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, + dst0, dst1, dst2, dst3); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst0, dst, 0, 2); + __lasx_xvstelm_d(dst0, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 2); + __lasx_xvstelm_d(dst1, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 2); + __lasx_xvstelm_d(dst2, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 0); + __lasx_xvstelm_d(dst3, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 2); + __lasx_xvstelm_d(dst3, dst, 8, 3); + dst += stride; + + if (16 == height) { + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src += stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, + tmp4, 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp4, tmp5, tmp6, tmp7); + dst -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, + tmp4, 0x20, tmp7, tmp6, 0x20, dst0, dst1, dst2, dst3); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, 128, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec0, vec2, vec4, vec6); + DUP4_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec1, vec3, vec5, vec7); + + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec4, offset, wgt, vec5, + offset, wgt, vec6, offset, wgt, vec7, tmp4, tmp5, tmp6, tmp7); + + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + tmp4 = __lasx_xvsra_h(tmp4, denom); + tmp5 = __lasx_xvsra_h(tmp5, denom); + tmp6 = __lasx_xvsra_h(tmp6, denom); + tmp7 = __lasx_xvsra_h(tmp7, denom); + + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_xvclip255_h, tmp4, tmp5, tmp6, tmp7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, + tmp6, dst0, dst1, dst2, dst3); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst0, dst, 0, 2); + __lasx_xvstelm_d(dst0, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 2); + __lasx_xvstelm_d(dst1, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 2); + __lasx_xvstelm_d(dst2, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 0); + __lasx_xvstelm_d(dst3, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 2); + __lasx_xvstelm_d(dst3, dst, 8, 3); + } +} + +static void avc_biwgt_8x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1; + __m256i src0, dst0; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + vec1 = __lasx_xvilvh_b(dst0, src0); + DUP2_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + tmp0, tmp1); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + DUP2_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp0, tmp1); + dst0 = __lasx_xvpickev_b(tmp1, tmp0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); +} + +static void avc_biwgt_8x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1, vec2, vec3; + __m256i src0, src1, dst0, dst1; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + uint8_t* dst_tmp = dst; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + tmp0 = __lasx_xvld(dst_tmp, 0); + DUP2_ARG2(__lasx_xvldx, dst_tmp, stride, dst_tmp, stride_2x, tmp1, tmp2); + tmp3 = __lasx_xvldx(dst_tmp, stride_3x); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, dst0, 128, dst1, 128, + src0, src1, dst0, dst1); + DUP2_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, vec0, vec2); + DUP2_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, vec1, vec3); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, dst0, dst1); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst + stride, 0, 1); + __lasx_xvstelm_d(dst1, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst1, dst + stride_3x, 0, 3); +} + +static void avc_biwgt_8x16_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m256i src0, src1, src2, src3, dst0, dst1, dst2, dst3; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + uint8_t* dst_tmp = dst; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src2 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src3 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst2 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst3 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, 128, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec0, vec2, vec4, vec6); + DUP4_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec1, vec3, vec5, vec7); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lasx_xvdp2add_h_b,offset, wgt, vec4, offset, wgt, vec5, + offset, wgt, vec6, offset, wgt, vec7, tmp4, tmp5, tmp6, tmp7); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + tmp4 = __lasx_xvsra_h(tmp4, denom); + tmp5 = __lasx_xvsra_h(tmp5, denom); + tmp6 = __lasx_xvsra_h(tmp6, denom); + tmp7 = __lasx_xvsra_h(tmp7, denom); + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_xvclip255_h, tmp4, tmp5, tmp6, tmp7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, + dst0, dst1, dst2, dst3) + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst + stride, 0, 1); + __lasx_xvstelm_d(dst1, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst1, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst + stride, 0, 1); + __lasx_xvstelm_d(dst2, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst2, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst3, dst, 0, 0); + __lasx_xvstelm_d(dst3, dst + stride, 0, 1); + __lasx_xvstelm_d(dst3, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst3, dst + stride_3x, 0, 3); +} + +void ff_biweight_h264_pixels8_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset) +{ + if (4 == height) { + avc_biwgt_8x4_lasx(src, dst, stride, log2_denom, weight_src, weight_dst, + offset); + } else if (8 == height) { + avc_biwgt_8x8_lasx(src, dst, stride, log2_denom, weight_src, weight_dst, + offset); + } else { + avc_biwgt_8x16_lasx(src, dst, stride, log2_denom, weight_src, weight_dst, + offset); + } +} + +static void avc_biwgt_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0; + __m256i src0, dst0; + __m256i tmp0, tmp1, denom, offset; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP2_ARG2(__lasx_xvldx, src, 0, src, stride, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP2_ARG2(__lasx_xvldx, dst, 0, dst, stride, tmp0, tmp1); + dst0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + tmp0 = __lasx_xvdp2add_h_b(offset, wgt, vec0); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp0 = __lasx_xvclip255_h(tmp0); + tmp0 = __lasx_xvpickev_b(tmp0, tmp0); + __lasx_xvstelm_w(tmp0, dst, 0, 0); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 1); +} + +static void avc_biwgt_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0; + __m256i src0, dst0; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + dst0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + dst0 = __lasx_xvilvh_b(dst0, src0); + vec0 = __lasx_xvpermi_q(vec0, dst0, 0x02); + tmp0 = __lasx_xvdp2add_h_b(offset, wgt, vec0); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp0 = __lasx_xvclip255_h(tmp0); + tmp0 = __lasx_xvpickev_b(tmp0, tmp0); + __lasx_xvstelm_w(tmp0, dst, 0, 0); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_w(tmp0, dst + stride_2x, 0, 4); + __lasx_xvstelm_w(tmp0, dst + stride_3x, 0, 5); +} + +static void avc_biwgt_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1; + __m256i src0, dst0; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp6, tmp4, tmp7, tmp5, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp4, tmp5, tmp6, tmp7); + dst -= stride_4x; + DUP4_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp6, tmp4, tmp7, tmp5, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + vec1 = __lasx_xvilvh_b(dst0, src0); + DUP2_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + tmp0, tmp1); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + DUP2_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp0, tmp1); + tmp0 = __lasx_xvpickev_b(tmp1, tmp0); + __lasx_xvstelm_w(tmp0, dst, 0, 0); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_w(tmp0, dst + stride_2x, 0, 2); + __lasx_xvstelm_w(tmp0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_w(tmp0, dst, 0, 4); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 5); + __lasx_xvstelm_w(tmp0, dst + stride_2x, 0, 6); + __lasx_xvstelm_w(tmp0, dst + stride_3x, 0, 7); +} + +void ff_biweight_h264_pixels4_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset) +{ + if (2 == height) { + avc_biwgt_4x2_lasx(src, dst, stride, log2_denom, weight_src, + weight_dst, offset); + } else if (4 == height) { + avc_biwgt_4x4_lasx(src, dst, stride, log2_denom, weight_src, + weight_dst, offset); + } else { + avc_biwgt_4x8_lasx(src, dst, stride, log2_denom, weight_src, + weight_dst, offset); + } +} + +void ff_weight_h264_pixels16_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset_in) +{ + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i zero = __lasx_xvldi(0); + __m256i src0, src1, src2, src3; + __m256i src0_l, src1_l, src2_l, src3_l, src0_h, src1_h, src2_h, src3_h; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i wgt, denom, offset; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, tmp4, + 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_h, src1_h, src2_h, src3_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + src2_l = __lasx_xvmul_h(wgt, src2_l); + src2_h = __lasx_xvmul_h(wgt, src2_h); + src3_l = __lasx_xvmul_h(wgt, src3_l); + src3_h = __lasx_xvmul_h(wgt, src3_h); + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, offset, + src1_h, offset, src0_l, src0_h, src1_l, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src2_l, offset, src2_h, offset, src3_l, offset, + src3_h, offset, src2_l, src2_h, src3_l, src3_h); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src2_l = __lasx_xvmaxi_h(src2_l, 0); + src2_h = __lasx_xvmaxi_h(src2_h, 0); + src3_l = __lasx_xvmaxi_h(src3_l, 0); + src3_h = __lasx_xvmaxi_h(src3_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + src2_l = __lasx_xvssrlrn_bu_h(src2_l, denom); + src2_h = __lasx_xvssrlrn_bu_h(src2_h, denom); + src3_l = __lasx_xvssrlrn_bu_h(src3_l, denom); + src3_h = __lasx_xvssrlrn_bu_h(src3_h, denom); + __lasx_xvstelm_d(src0_l, src, 0, 0); + __lasx_xvstelm_d(src0_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src0_l, src, 0, 2); + __lasx_xvstelm_d(src0_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 0); + __lasx_xvstelm_d(src1_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 2); + __lasx_xvstelm_d(src1_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 0); + __lasx_xvstelm_d(src2_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 2); + __lasx_xvstelm_d(src2_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 0); + __lasx_xvstelm_d(src3_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 2); + __lasx_xvstelm_d(src3_h, src, 8, 2); + src += stride; + + if (16 == height) { + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, + tmp4, 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_h, src1_h, src2_h, src3_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + src2_l = __lasx_xvmul_h(wgt, src2_l); + src2_h = __lasx_xvmul_h(wgt, src2_h); + src3_l = __lasx_xvmul_h(wgt, src3_l); + src3_h = __lasx_xvmul_h(wgt, src3_h); + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, + offset, src1_h, offset, src0_l, src0_h, src1_l, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src2_l, offset, src2_h, offset, src3_l, + offset, src3_h, offset, src2_l, src2_h, src3_l, src3_h); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src2_l = __lasx_xvmaxi_h(src2_l, 0); + src2_h = __lasx_xvmaxi_h(src2_h, 0); + src3_l = __lasx_xvmaxi_h(src3_l, 0); + src3_h = __lasx_xvmaxi_h(src3_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + src2_l = __lasx_xvssrlrn_bu_h(src2_l, denom); + src2_h = __lasx_xvssrlrn_bu_h(src2_h, denom); + src3_l = __lasx_xvssrlrn_bu_h(src3_l, denom); + src3_h = __lasx_xvssrlrn_bu_h(src3_h, denom); + __lasx_xvstelm_d(src0_l, src, 0, 0); + __lasx_xvstelm_d(src0_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src0_l, src, 0, 2); + __lasx_xvstelm_d(src0_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 0); + __lasx_xvstelm_d(src1_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 2); + __lasx_xvstelm_d(src1_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 0); + __lasx_xvstelm_d(src2_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 2); + __lasx_xvstelm_d(src2_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 0); + __lasx_xvstelm_d(src3_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 2); + __lasx_xvstelm_d(src3_h, src, 8, 2); + } +} + +static void avc_wgt_8x4_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i wgt, zero = __lasx_xvldi(0); + __m256i src0, src0_h, src0_l; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + src0_l = __lasx_xvilvl_b(zero, src0); + src0_h = __lasx_xvilvh_b(zero, src0); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src0_l = __lasx_xvsadd_h(src0_l, offset); + src0_h = __lasx_xvsadd_h(src0_h, offset); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + + src0 = __lasx_xvpickev_d(src0_h, src0_l); + __lasx_xvstelm_d(src0, src, 0, 0); + __lasx_xvstelm_d(src0, src + stride, 0, 1); + __lasx_xvstelm_d(src0, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src0, src + stride_3x, 0, 3); +} + +static void avc_wgt_8x8_lasx(uint8_t *src, ptrdiff_t stride, int32_t log2_denom, + int32_t src_weight, int32_t offset_in) +{ + __m256i src0, src1, src0_h, src0_l, src1_h, src1_l, zero = __lasx_xvldi(0); + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset, wgt; + uint32_t offset_val; + uint8_t* src_tmp = src; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(src_weight); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP2_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, src0_l, src1_l); + DUP2_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, src0_h, src1_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, offset, + src1_h, offset, src0_l, src0_h, src1_l, src1_h); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + + DUP2_ARG2(__lasx_xvpickev_d, src0_h, src0_l, src1_h, src1_l, src0, src1); + __lasx_xvstelm_d(src0, src, 0, 0); + __lasx_xvstelm_d(src0, src + stride, 0, 1); + __lasx_xvstelm_d(src0, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src0, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src1, src, 0, 0); + __lasx_xvstelm_d(src1, src + stride, 0, 1); + __lasx_xvstelm_d(src1, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src1, src + stride_3x, 0, 3); +} + +static void avc_wgt_8x16_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t src_weight, + int32_t offset_in) +{ + __m256i src0, src1, src2, src3; + __m256i src0_h, src0_l, src1_h, src1_l, src2_h, src2_l, src3_h, src3_l; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset, wgt; + __m256i zero = __lasx_xvldi(0); + uint32_t offset_val; + uint8_t* src_tmp = src; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(src_weight); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src2 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src3 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, zero, src2, zero, src3, + src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, zero, src2, zero, src3, + src0_h, src1_h, src2_h, src3_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + src2_l = __lasx_xvmul_h(wgt, src2_l); + src2_h = __lasx_xvmul_h(wgt, src2_h); + src3_l = __lasx_xvmul_h(wgt, src3_l); + src3_h = __lasx_xvmul_h(wgt, src3_h); + + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, offset, + src1_h, offset, src0_l, src0_h, src1_l, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src2_l, offset, src2_h, offset, src3_l, offset, + src3_h, offset, src2_l, src2_h, src3_l, src3_h); + + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src2_l = __lasx_xvmaxi_h(src2_l, 0); + src2_h = __lasx_xvmaxi_h(src2_h, 0); + src3_l = __lasx_xvmaxi_h(src3_l, 0); + src3_h = __lasx_xvmaxi_h(src3_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + src2_l = __lasx_xvssrlrn_bu_h(src2_l, denom); + src2_h = __lasx_xvssrlrn_bu_h(src2_h, denom); + src3_l = __lasx_xvssrlrn_bu_h(src3_l, denom); + src3_h = __lasx_xvssrlrn_bu_h(src3_h, denom); + DUP4_ARG2(__lasx_xvpickev_d, src0_h, src0_l, src1_h, src1_l, src2_h, src2_l, + src3_h, src3_l, src0, src1, src2, src3); + + __lasx_xvstelm_d(src0, src, 0, 0); + __lasx_xvstelm_d(src0, src + stride, 0, 1); + __lasx_xvstelm_d(src0, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src0, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src1, src, 0, 0); + __lasx_xvstelm_d(src1, src + stride, 0, 1); + __lasx_xvstelm_d(src1, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src1, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src2, src, 0, 0); + __lasx_xvstelm_d(src2, src + stride, 0, 1); + __lasx_xvstelm_d(src2, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src2, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src3, src, 0, 0); + __lasx_xvstelm_d(src3, src + stride, 0, 1); + __lasx_xvstelm_d(src3, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src3, src + stride_3x, 0, 3); +} + +void ff_weight_h264_pixels8_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset) +{ + if (4 == height) { + avc_wgt_8x4_lasx(src, stride, log2_denom, weight_src, offset); + } else if (8 == height) { + avc_wgt_8x8_lasx(src, stride, log2_denom, weight_src, offset); + } else { + avc_wgt_8x16_lasx(src, stride, log2_denom, weight_src, offset); + } +} + +static void avc_wgt_4x2_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + uint32_t offset_val; + __m256i wgt, zero = __lasx_xvldi(0); + __m256i src0, tmp0, tmp1, denom, offset; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP2_ARG2(__lasx_xvldx, src, 0, src, stride, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + src0 = __lasx_xvilvl_b(zero, src0); + src0 = __lasx_xvmul_h(wgt, src0); + src0 = __lasx_xvsadd_h(src0, offset); + src0 = __lasx_xvmaxi_h(src0, 0); + src0 = __lasx_xvssrlrn_bu_h(src0, denom); + __lasx_xvstelm_w(src0, src, 0, 0); + __lasx_xvstelm_w(src0, src + stride, 0, 1); +} + +static void avc_wgt_4x4_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + __m256i wgt; + __m256i src0, tmp0, tmp1, tmp2, tmp3, denom, offset; + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + src0 = __lasx_vext2xv_hu_bu(src0); + src0 = __lasx_xvmul_h(wgt, src0); + src0 = __lasx_xvsadd_h(src0, offset); + src0 = __lasx_xvmaxi_h(src0, 0); + src0 = __lasx_xvssrlrn_bu_h(src0, denom); + __lasx_xvstelm_w(src0, src, 0, 0); + __lasx_xvstelm_w(src0, src + stride, 0, 1); + __lasx_xvstelm_w(src0, src + stride_2x, 0, 4); + __lasx_xvstelm_w(src0, src + stride_3x, 0, 5); +} + +static void avc_wgt_4x8_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + __m256i src0, src0_h, src0_l; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset; + __m256i wgt, zero = __lasx_xvldi(0); + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src -= stride_4x; + DUP4_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp6, tmp4, tmp7, + tmp5, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + src0_l = __lasx_xvilvl_b(zero, src0); + src0_h = __lasx_xvilvh_b(zero, src0); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src0_l = __lasx_xvsadd_h(src0_l, offset); + src0_h = __lasx_xvsadd_h(src0_h, offset); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + __lasx_xvstelm_w(src0_l, src, 0, 0); + __lasx_xvstelm_w(src0_l, src + stride, 0, 1); + __lasx_xvstelm_w(src0_h, src + stride_2x, 0, 0); + __lasx_xvstelm_w(src0_h, src + stride_3x, 0, 1); + src += stride_4x; + __lasx_xvstelm_w(src0_l, src, 0, 4); + __lasx_xvstelm_w(src0_l, src + stride, 0, 5); + __lasx_xvstelm_w(src0_h, src + stride_2x, 0, 4); + __lasx_xvstelm_w(src0_h, src + stride_3x, 0, 5); +} + +void ff_weight_h264_pixels4_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset) +{ + if (2 == height) { + avc_wgt_4x2_lasx(src, stride, log2_denom, weight_src, offset); + } else if (4 == height) { + avc_wgt_4x4_lasx(src, stride, log2_denom, weight_src, offset); + } else { + avc_wgt_4x8_lasx(src, stride, log2_denom, weight_src, offset); + } +} + +void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride) +{ + __m256i src0, dst0, dst1, dst2, dst3, zero; + __m256i tmp0, tmp1; + uint8_t* _dst1 = _dst + stride; + uint8_t* _dst2 = _dst1 + stride; + uint8_t* _dst3 = _dst2 + stride; + + src0 = __lasx_xvld(_src, 0); + dst0 = __lasx_xvldrepl_w(_dst, 0); + dst1 = __lasx_xvldrepl_w(_dst1, 0); + dst2 = __lasx_xvldrepl_w(_dst2, 0); + dst3 = __lasx_xvldrepl_w(_dst3, 0); + tmp0 = __lasx_xvilvl_w(dst1, dst0); + tmp1 = __lasx_xvilvl_w(dst3, dst2); + dst0 = __lasx_xvilvl_d(tmp1, tmp0); + tmp0 = __lasx_vext2xv_hu_bu(dst0); + zero = __lasx_xvldi(0); + tmp1 = __lasx_xvadd_h(src0, tmp0); + dst0 = __lasx_xvpickev_b(tmp1, tmp1); + __lasx_xvstelm_w(dst0, _dst, 0, 0); + __lasx_xvstelm_w(dst0, _dst1, 0, 1); + __lasx_xvstelm_w(dst0, _dst2, 0, 4); + __lasx_xvstelm_w(dst0, _dst3, 0, 5); + __lasx_xvst(zero, _src, 0); +} + +void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride) +{ + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m256i tmp0, tmp1, tmp2, tmp3; + __m256i zero = __lasx_xvldi(0); + uint8_t *_dst1 = _dst + stride; + uint8_t *_dst2 = _dst1 + stride; + uint8_t *_dst3 = _dst2 + stride; + uint8_t *_dst4 = _dst3 + stride; + uint8_t *_dst5 = _dst4 + stride; + uint8_t *_dst6 = _dst5 + stride; + uint8_t *_dst7 = _dst6 + stride; + + src0 = __lasx_xvld(_src, 0); + src1 = __lasx_xvld(_src, 32); + src2 = __lasx_xvld(_src, 64); + src3 = __lasx_xvld(_src, 96); + dst0 = __lasx_xvldrepl_d(_dst, 0); + dst1 = __lasx_xvldrepl_d(_dst1, 0); + dst2 = __lasx_xvldrepl_d(_dst2, 0); + dst3 = __lasx_xvldrepl_d(_dst3, 0); + dst4 = __lasx_xvldrepl_d(_dst4, 0); + dst5 = __lasx_xvldrepl_d(_dst5, 0); + dst6 = __lasx_xvldrepl_d(_dst6, 0); + dst7 = __lasx_xvldrepl_d(_dst7, 0); + tmp0 = __lasx_xvilvl_d(dst1, dst0); + tmp1 = __lasx_xvilvl_d(dst3, dst2); + tmp2 = __lasx_xvilvl_d(dst5, dst4); + tmp3 = __lasx_xvilvl_d(dst7, dst6); + dst0 = __lasx_vext2xv_hu_bu(tmp0); + dst1 = __lasx_vext2xv_hu_bu(tmp1); + dst1 = __lasx_vext2xv_hu_bu(tmp1); + dst2 = __lasx_vext2xv_hu_bu(tmp2); + dst3 = __lasx_vext2xv_hu_bu(tmp3); + tmp0 = __lasx_xvadd_h(src0, dst0); + tmp1 = __lasx_xvadd_h(src1, dst1); + tmp2 = __lasx_xvadd_h(src2, dst2); + tmp3 = __lasx_xvadd_h(src3, dst3); + dst1 = __lasx_xvpickev_b(tmp1, tmp0); + dst2 = __lasx_xvpickev_b(tmp3, tmp2); + __lasx_xvst(zero, _src, 0); + __lasx_xvst(zero, _src, 32); + __lasx_xvst(zero, _src, 64); + __lasx_xvst(zero, _src, 96); + __lasx_xvstelm_d(dst1, _dst, 0, 0); + __lasx_xvstelm_d(dst1, _dst1, 0, 2); + __lasx_xvstelm_d(dst1, _dst2, 0, 1); + __lasx_xvstelm_d(dst1, _dst3, 0, 3); + __lasx_xvstelm_d(dst2, _dst4, 0, 0); + __lasx_xvstelm_d(dst2, _dst5, 0, 2); + __lasx_xvstelm_d(dst2, _dst6, 0, 1); + __lasx_xvstelm_d(dst2, _dst7, 0, 3); +} diff --git a/libavcodec/loongarch/h264dsp_lasx.h b/libavcodec/loongarch/h264dsp_lasx.h new file mode 100644 index 0000000000..538c14c936 --- /dev/null +++ b/libavcodec/loongarch/h264dsp_lasx.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Xiwei Gu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H +#define AVCODEC_LOONGARCH_H264DSP_LASX_H + +#include "libavcodec/h264dec.h" + +void ff_h264_h_lpf_luma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_luma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_h_lpf_luma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_v_lpf_luma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_h_lpf_chroma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_chroma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_h_lpf_chroma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_v_lpf_chroma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_biweight_h264_pixels16_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset_in); +void ff_biweight_h264_pixels8_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset); +void ff_biweight_h264_pixels4_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset); +void ff_weight_h264_pixels16_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset_in); +void ff_weight_h264_pixels8_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset); +void ff_weight_h264_pixels4_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset); +void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride); + +void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride); +#endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H From 5ff58b77bb1f44a2074967cb0e0b7db3b437df10 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Wed, 15 Dec 2021 11:51:08 +0800 Subject: [PATCH 477/894] avcodec: [loongarch] Optimize h264idct with LASX. ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:282 after :293 Change-Id: Ia8889935a6359630dd5dbb61263287f1cb24a0a4 Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 3 +- libavcodec/loongarch/h264dsp_init_loongarch.c | 15 + libavcodec/loongarch/h264dsp_lasx.h | 23 + libavcodec/loongarch/h264idct_lasx.c | 498 ++++++++++++++++++ 4 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 libavcodec/loongarch/h264idct_lasx.c diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index df43151dbd..242a2be290 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -3,4 +3,5 @@ OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o -LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o +LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ + loongarch/h264idct_lasx.o diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c index ddc0877a74..0985c2fe8a 100644 --- a/libavcodec/loongarch/h264dsp_init_loongarch.c +++ b/libavcodec/loongarch/h264dsp_init_loongarch.c @@ -53,6 +53,21 @@ av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_8_lasx; c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_8_lasx; c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels4_8_lasx; + + c->h264_idct_add = ff_h264_idct_add_lasx; + c->h264_idct8_add = ff_h264_idct8_addblk_lasx; + c->h264_idct_dc_add = ff_h264_idct4x4_addblk_dc_lasx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_addblk_lasx; + c->h264_idct_add16 = ff_h264_idct_add16_lasx; + c->h264_idct8_add4 = ff_h264_idct8_add4_lasx; + + if (chroma_format_idc <= 1) + c->h264_idct_add8 = ff_h264_idct_add8_lasx; + else + c->h264_idct_add8 = ff_h264_idct_add8_422_lasx; + + c->h264_idct_add16intra = ff_h264_idct_add16_intra_lasx; + c->h264_luma_dc_dequant_idct = ff_h264_deq_idct_luma_dc_lasx; } } } diff --git a/libavcodec/loongarch/h264dsp_lasx.h b/libavcodec/loongarch/h264dsp_lasx.h index 538c14c936..bfd567fffa 100644 --- a/libavcodec/loongarch/h264dsp_lasx.h +++ b/libavcodec/loongarch/h264dsp_lasx.h @@ -65,4 +65,27 @@ void ff_weight_h264_pixels4_8_lasx(uint8_t *src, ptrdiff_t stride, void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride); void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride); +void ff_h264_idct_add_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride); +void ff_h264_idct8_addblk_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride); +void ff_h264_idct4x4_addblk_dc_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride); +void ff_h264_idct8_dc_addblk_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride); +void ff_h264_idct_add16_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct8_add4_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct_add8_lasx(uint8_t **dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct_add8_422_lasx(uint8_t **dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct_add16_intra_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_deq_idct_luma_dc_lasx(int16_t *dst, int16_t *src, + int32_t de_qval); #endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H diff --git a/libavcodec/loongarch/h264idct_lasx.c b/libavcodec/loongarch/h264idct_lasx.c new file mode 100644 index 0000000000..46bd3b74d5 --- /dev/null +++ b/libavcodec/loongarch/h264idct_lasx.c @@ -0,0 +1,498 @@ +/* + * Loongson LASX optimized h264dsp + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Xiwei Gu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "h264dsp_lasx.h" +#include "libavcodec/bit_depth_template.c" + +#define AVC_ITRANS_H(in0, in1, in2, in3, out0, out1, out2, out3) \ +{ \ + __m256i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + \ + tmp0_m = __lasx_xvadd_h(in0, in2); \ + tmp1_m = __lasx_xvsub_h(in0, in2); \ + tmp2_m = __lasx_xvsrai_h(in1, 1); \ + tmp2_m = __lasx_xvsub_h(tmp2_m, in3); \ + tmp3_m = __lasx_xvsrai_h(in3, 1); \ + tmp3_m = __lasx_xvadd_h(in1, tmp3_m); \ + \ + LASX_BUTTERFLY_4_H(tmp0_m, tmp1_m, tmp2_m, tmp3_m, \ + out0, out1, out2, out3); \ +} + +void ff_h264_idct_add_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride) +{ + __m256i src0_m, src1_m, src2_m, src3_m; + __m256i dst0_m, dst1_m; + __m256i hres0, hres1, hres2, hres3, vres0, vres1, vres2, vres3; + __m256i inp0_m, inp1_m, res0_m, src1, src3; + __m256i src0 = __lasx_xvld(src, 0); + __m256i src2 = __lasx_xvld(src, 16); + __m256i zero = __lasx_xvldi(0); + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __lasx_xvst(zero, src, 0); + DUP2_ARG2(__lasx_xvilvh_d, src0, src0, src2, src2, src1, src3); + AVC_ITRANS_H(src0, src1, src2, src3, hres0, hres1, hres2, hres3); + LASX_TRANSPOSE4x4_H(hres0, hres1, hres2, hres3, hres0, hres1, hres2, hres3); + AVC_ITRANS_H(hres0, hres1, hres2, hres3, vres0, vres1, vres2, vres3); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, src0_m, src1_m, src2_m, src3_m); + DUP4_ARG2(__lasx_xvld, dst, 0, dst + dst_stride, 0, dst + dst_stride_2x, + 0, dst + dst_stride_3x, 0, src0_m, src1_m, src2_m, src3_m); + DUP2_ARG2(__lasx_xvilvl_d, vres1, vres0, vres3, vres2, inp0_m, inp1_m); + inp0_m = __lasx_xvpermi_q(inp1_m, inp0_m, 0x20); + inp0_m = __lasx_xvsrari_h(inp0_m, 6); + DUP2_ARG2(__lasx_xvilvl_w, src1_m, src0_m, src3_m, src2_m, dst0_m, dst1_m); + dst0_m = __lasx_xvilvl_d(dst1_m, dst0_m); + res0_m = __lasx_vext2xv_hu_bu(dst0_m); + res0_m = __lasx_xvadd_h(res0_m, inp0_m); + res0_m = __lasx_xvclip255_h(res0_m); + dst0_m = __lasx_xvpickev_b(res0_m, res0_m); + __lasx_xvstelm_w(dst0_m, dst, 0, 0); + __lasx_xvstelm_w(dst0_m, dst + dst_stride, 0, 1); + __lasx_xvstelm_w(dst0_m, dst + dst_stride_2x, 0, 4); + __lasx_xvstelm_w(dst0_m, dst + dst_stride_3x, 0, 5); +} + +void ff_h264_idct8_addblk_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i vec0, vec1, vec2, vec3; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i res0, res1, res2, res3, res4, res5, res6, res7; + __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m256i zero = __lasx_xvldi(0); + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + src[0] += 32; + DUP4_ARG2(__lasx_xvld, src, 0, src, 16, src, 32, src, 48, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvld, src, 64, src, 80, src, 96, src, 112, + src4, src5, src6, src7); + __lasx_xvst(zero, src, 0); + __lasx_xvst(zero, src, 32); + __lasx_xvst(zero, src, 64); + __lasx_xvst(zero, src, 96); + + vec0 = __lasx_xvadd_h(src0, src4); + vec1 = __lasx_xvsub_h(src0, src4); + vec2 = __lasx_xvsrai_h(src2, 1); + vec2 = __lasx_xvsub_h(vec2, src6); + vec3 = __lasx_xvsrai_h(src6, 1); + vec3 = __lasx_xvadd_h(src2, vec3); + + LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, tmp0, tmp1, tmp2, tmp3); + + vec0 = __lasx_xvsrai_h(src7, 1); + vec0 = __lasx_xvsub_h(src5, vec0); + vec0 = __lasx_xvsub_h(vec0, src3); + vec0 = __lasx_xvsub_h(vec0, src7); + + vec1 = __lasx_xvsrai_h(src3, 1); + vec1 = __lasx_xvsub_h(src1, vec1); + vec1 = __lasx_xvadd_h(vec1, src7); + vec1 = __lasx_xvsub_h(vec1, src3); + + vec2 = __lasx_xvsrai_h(src5, 1); + vec2 = __lasx_xvsub_h(vec2, src1); + vec2 = __lasx_xvadd_h(vec2, src7); + vec2 = __lasx_xvadd_h(vec2, src5); + + vec3 = __lasx_xvsrai_h(src1, 1); + vec3 = __lasx_xvadd_h(src3, vec3); + vec3 = __lasx_xvadd_h(vec3, src5); + vec3 = __lasx_xvadd_h(vec3, src1); + + tmp4 = __lasx_xvsrai_h(vec3, 2); + tmp4 = __lasx_xvadd_h(tmp4, vec0); + tmp5 = __lasx_xvsrai_h(vec2, 2); + tmp5 = __lasx_xvadd_h(tmp5, vec1); + tmp6 = __lasx_xvsrai_h(vec1, 2); + tmp6 = __lasx_xvsub_h(tmp6, vec2); + tmp7 = __lasx_xvsrai_h(vec0, 2); + tmp7 = __lasx_xvsub_h(vec3, tmp7); + + LASX_BUTTERFLY_8_H(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, + res0, res1, res2, res3, res4, res5, res6, res7); + LASX_TRANSPOSE8x8_H(res0, res1, res2, res3, res4, res5, res6, res7, + res0, res1, res2, res3, res4, res5, res6, res7); + + DUP4_ARG1(__lasx_vext2xv_w_h, res0, res1, res2, res3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_vext2xv_w_h, res4, res5, res6, res7, + tmp4, tmp5, tmp6, tmp7); + vec0 = __lasx_xvadd_w(tmp0, tmp4); + vec1 = __lasx_xvsub_w(tmp0, tmp4); + + vec2 = __lasx_xvsrai_w(tmp2, 1); + vec2 = __lasx_xvsub_w(vec2, tmp6); + vec3 = __lasx_xvsrai_w(tmp6, 1); + vec3 = __lasx_xvadd_w(vec3, tmp2); + + tmp0 = __lasx_xvadd_w(vec0, vec3); + tmp2 = __lasx_xvadd_w(vec1, vec2); + tmp4 = __lasx_xvsub_w(vec1, vec2); + tmp6 = __lasx_xvsub_w(vec0, vec3); + + vec0 = __lasx_xvsrai_w(tmp7, 1); + vec0 = __lasx_xvsub_w(tmp5, vec0); + vec0 = __lasx_xvsub_w(vec0, tmp3); + vec0 = __lasx_xvsub_w(vec0, tmp7); + + vec1 = __lasx_xvsrai_w(tmp3, 1); + vec1 = __lasx_xvsub_w(tmp1, vec1); + vec1 = __lasx_xvadd_w(vec1, tmp7); + vec1 = __lasx_xvsub_w(vec1, tmp3); + + vec2 = __lasx_xvsrai_w(tmp5, 1); + vec2 = __lasx_xvsub_w(vec2, tmp1); + vec2 = __lasx_xvadd_w(vec2, tmp7); + vec2 = __lasx_xvadd_w(vec2, tmp5); + + vec3 = __lasx_xvsrai_w(tmp1, 1); + vec3 = __lasx_xvadd_w(tmp3, vec3); + vec3 = __lasx_xvadd_w(vec3, tmp5); + vec3 = __lasx_xvadd_w(vec3, tmp1); + + tmp1 = __lasx_xvsrai_w(vec3, 2); + tmp1 = __lasx_xvadd_w(tmp1, vec0); + tmp3 = __lasx_xvsrai_w(vec2, 2); + tmp3 = __lasx_xvadd_w(tmp3, vec1); + tmp5 = __lasx_xvsrai_w(vec1, 2); + tmp5 = __lasx_xvsub_w(tmp5, vec2); + tmp7 = __lasx_xvsrai_w(vec0, 2); + tmp7 = __lasx_xvsub_w(vec3, tmp7); + + LASX_BUTTERFLY_4_W(tmp0, tmp2, tmp5, tmp7, res0, res1, res6, res7); + LASX_BUTTERFLY_4_W(tmp4, tmp6, tmp1, tmp3, res2, res3, res4, res5); + + DUP4_ARG2(__lasx_xvsrai_w, res0, 6, res1, 6, res2, 6, res3, 6, + res0, res1, res2, res3); + DUP4_ARG2(__lasx_xvsrai_w, res4, 6, res5, 6, res6, 6, res7, 6, + res4, res5, res6, res7); + DUP4_ARG2(__lasx_xvpickev_h, res1, res0, res3, res2, res5, res4, res7, + res6, res0, res1, res2, res3); + DUP4_ARG2(__lasx_xvpermi_d, res0, 0xd8, res1, 0xd8, res2, 0xd8, res3, 0xd8, + res0, res1, res2, res3); + + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst0, dst1, dst2, dst3); + dst += dst_stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst4, dst5, dst6, dst7); + dst -= dst_stride_4x; + DUP4_ARG2(__lasx_xvilvl_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, zero, dst4, zero, dst5, zero, dst6, zero, dst7, + dst4, dst5, dst6, dst7); + DUP4_ARG3(__lasx_xvpermi_q, dst1, dst0, 0x20, dst3, dst2, 0x20, dst5, + dst4, 0x20, dst7, dst6, 0x20, dst0, dst1, dst2, dst3); + res0 = __lasx_xvadd_h(res0, dst0); + res1 = __lasx_xvadd_h(res1, dst1); + res2 = __lasx_xvadd_h(res2, dst2); + res3 = __lasx_xvadd_h(res3, dst3); + DUP4_ARG1(__lasx_xvclip255_h, res0, res1, res2, res3, res0, res1, + res2, res3); + DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, res0, res1); + __lasx_xvstelm_d(res0, dst, 0, 0); + __lasx_xvstelm_d(res0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(res0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(res0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(res1, dst, 0, 0); + __lasx_xvstelm_d(res1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(res1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(res1, dst + dst_stride_3x, 0, 3); +} + +void ff_h264_idct4x4_addblk_dc_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride) +{ + const int16_t dc = (src[0] + 32) >> 6; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m256i pred, out; + __m256i src0, src1, src2, src3; + __m256i input_dc = __lasx_xvreplgr2vr_h(dc); + + src[0] = 0; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvilvl_w, src1, src0, src3, src2, src0, src1); + + pred = __lasx_xvpermi_q(src0, src1, 0x02); + pred = __lasx_xvaddw_h_h_bu(input_dc, pred); + pred = __lasx_xvclip255_h(pred); + out = __lasx_xvpickev_b(pred, pred); + __lasx_xvstelm_w(out, dst, 0, 0); + __lasx_xvstelm_w(out, dst + dst_stride, 0, 1); + __lasx_xvstelm_w(out, dst + dst_stride_2x, 0, 4); + __lasx_xvstelm_w(out, dst + dst_stride_3x, 0, 5); +} + +void ff_h264_idct8_dc_addblk_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride) +{ + int32_t dc_val; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m256i dc; + + dc_val = (src[0] + 32) >> 6; + dc = __lasx_xvreplgr2vr_h(dc_val); + + src[0] = 0; + + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst0, dst1, dst2, dst3); + dst += dst_stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst4, dst5, dst6, dst7); + dst -= dst_stride_4x; + DUP4_ARG1(__lasx_vext2xv_hu_bu, dst0, dst1, dst2, dst3, + dst0, dst1, dst2, dst3); + DUP4_ARG1(__lasx_vext2xv_hu_bu, dst4, dst5, dst6, dst7, + dst4, dst5, dst6, dst7); + DUP4_ARG3(__lasx_xvpermi_q, dst1, dst0, 0x20, dst3, dst2, 0x20, dst5, + dst4, 0x20, dst7, dst6, 0x20, dst0, dst1, dst2, dst3); + dst0 = __lasx_xvadd_h(dst0, dc); + dst1 = __lasx_xvadd_h(dst1, dc); + dst2 = __lasx_xvadd_h(dst2, dc); + dst3 = __lasx_xvadd_h(dst3, dc); + DUP4_ARG1(__lasx_xvclip255_h, dst0, dst1, dst2, dst3, + dst0, dst1, dst2, dst3); + DUP2_ARG2(__lasx_xvpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(dst0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(dst0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(dst1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(dst1, dst + dst_stride_3x, 0, 3); +} + +void ff_h264_idct_add16_lasx(uint8_t *dst, + const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 0; i < 16; i++) { + int32_t nnz = nzc[scan8[i]]; + + if (nnz) { + if (nnz == 1 && ((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else + ff_h264_idct_add_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + } +} + +void ff_h264_idct8_add4_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t cnt; + + for (cnt = 0; cnt < 16; cnt += 4) { + int32_t nnz = nzc[scan8[cnt]]; + + if (nnz) { + if (nnz == 1 && ((dctcoef *) block)[cnt * 16]) + ff_h264_idct8_dc_addblk_lasx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + else + ff_h264_idct8_addblk_lasx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + } + } +} + + +void ff_h264_idct_add8_lasx(uint8_t **dst, + const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 16; i < 20; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 32; i < 36; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_idct_add8_422_lasx(uint8_t **dst, + const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 16; i < 20; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 32; i < 36; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 20; i < 24; i++) { + if (nzc[scan8[i + 4]]) + ff_h264_idct_add_lasx(dst[0] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 36; i < 40; i++) { + if (nzc[scan8[i + 4]]) + ff_h264_idct_add_lasx(dst[1] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_idct_add16_intra_lasx(uint8_t *dst, + const int32_t *blk_offset, + int16_t *block, + int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 0; i < 16; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_deq_idct_luma_dc_lasx(int16_t *dst, int16_t *src, + int32_t de_qval) +{ +#define DC_DEST_STRIDE 16 + + __m256i src0, src1, src2, src3; + __m256i vec0, vec1, vec2, vec3; + __m256i tmp0, tmp1, tmp2, tmp3; + __m256i hres0, hres1, hres2, hres3; + __m256i vres0, vres1, vres2, vres3; + __m256i de_q_vec = __lasx_xvreplgr2vr_w(de_qval); + + DUP4_ARG2(__lasx_xvld, src, 0, src, 8, src, 16, src, 24, + src0, src1, src2, src3); + LASX_TRANSPOSE4x4_H(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3); + LASX_BUTTERFLY_4_H(tmp0, tmp2, tmp3, tmp1, vec0, vec3, vec2, vec1); + LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, hres0, hres3, hres2, hres1); + LASX_TRANSPOSE4x4_H(hres0, hres1, hres2, hres3, + hres0, hres1, hres2, hres3); + LASX_BUTTERFLY_4_H(hres0, hres1, hres3, hres2, vec0, vec3, vec2, vec1); + LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, vres0, vres1, vres2, vres3); + DUP4_ARG1(__lasx_vext2xv_w_h, vres0, vres1, vres2, vres3, + vres0, vres1, vres2, vres3); + DUP2_ARG3(__lasx_xvpermi_q, vres1, vres0, 0x20, vres3, vres2, 0x20, + vres0, vres1); + + vres0 = __lasx_xvmul_w(vres0, de_q_vec); + vres1 = __lasx_xvmul_w(vres1, de_q_vec); + + vres0 = __lasx_xvsrari_w(vres0, 8); + vres1 = __lasx_xvsrari_w(vres1, 8); + vec0 = __lasx_xvpickev_h(vres1, vres0); + vec0 = __lasx_xvpermi_d(vec0, 0xd8); + __lasx_xvstelm_h(vec0, dst + 0 * DC_DEST_STRIDE, 0, 0); + __lasx_xvstelm_h(vec0, dst + 2 * DC_DEST_STRIDE, 0, 1); + __lasx_xvstelm_h(vec0, dst + 8 * DC_DEST_STRIDE, 0, 2); + __lasx_xvstelm_h(vec0, dst + 10 * DC_DEST_STRIDE, 0, 3); + __lasx_xvstelm_h(vec0, dst + 1 * DC_DEST_STRIDE, 0, 4); + __lasx_xvstelm_h(vec0, dst + 3 * DC_DEST_STRIDE, 0, 5); + __lasx_xvstelm_h(vec0, dst + 9 * DC_DEST_STRIDE, 0, 6); + __lasx_xvstelm_h(vec0, dst + 11 * DC_DEST_STRIDE, 0, 7); + __lasx_xvstelm_h(vec0, dst + 4 * DC_DEST_STRIDE, 0, 8); + __lasx_xvstelm_h(vec0, dst + 6 * DC_DEST_STRIDE, 0, 9); + __lasx_xvstelm_h(vec0, dst + 12 * DC_DEST_STRIDE, 0, 10); + __lasx_xvstelm_h(vec0, dst + 14 * DC_DEST_STRIDE, 0, 11); + __lasx_xvstelm_h(vec0, dst + 5 * DC_DEST_STRIDE, 0, 12); + __lasx_xvstelm_h(vec0, dst + 7 * DC_DEST_STRIDE, 0, 13); + __lasx_xvstelm_h(vec0, dst + 13 * DC_DEST_STRIDE, 0, 14); + __lasx_xvstelm_h(vec0, dst + 15 * DC_DEST_STRIDE, 0, 15); + +#undef DC_DEST_STRIDE +} From 1ccc45896096b39b9a0d5650618d384df30d15e4 Mon Sep 17 00:00:00 2001 From: Jin Bo Date: Wed, 15 Dec 2021 11:51:09 +0800 Subject: [PATCH 478/894] avcodec: [loongarch] Optimize h264_deblock with LASX. ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:293 after :295 Change-Id: I5ff6cba4eaca0c4218c0c97b880ca500e35f9c87 Signed-off-by: Hao Chen Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 3 +- libavcodec/loongarch/h264_deblock_lasx.c | 147 ++++++++++++++++++ libavcodec/loongarch/h264dsp_init_loongarch.c | 2 + libavcodec/loongarch/h264dsp_lasx.h | 6 + 4 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 libavcodec/loongarch/h264_deblock_lasx.c diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 242a2be290..1e1fe3fd48 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -4,4 +4,5 @@ OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ - loongarch/h264idct_lasx.o + loongarch/h264idct_lasx.o \ + loongarch/h264_deblock_lasx.o diff --git a/libavcodec/loongarch/h264_deblock_lasx.c b/libavcodec/loongarch/h264_deblock_lasx.c new file mode 100644 index 0000000000..c89bea9a84 --- /dev/null +++ b/libavcodec/loongarch/h264_deblock_lasx.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Xiwei Gu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/bit_depth_template.c" +#include "h264dsp_lasx.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +#define H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(edges, step, mask_mv, dir, \ + d_idx, mask_dir) \ +do { \ + int b_idx = 0; \ + int step_x4 = step << 2; \ + int d_idx_12 = d_idx + 12; \ + int d_idx_52 = d_idx + 52; \ + int d_idx_x4 = d_idx << 2; \ + int d_idx_x4_48 = d_idx_x4 + 48; \ + int dir_x32 = dir * 32; \ + uint8_t *ref_t = (uint8_t*)ref; \ + uint8_t *mv_t = (uint8_t*)mv; \ + uint8_t *nnz_t = (uint8_t*)nnz; \ + uint8_t *bS_t = (uint8_t*)bS; \ + mask_mv <<= 3; \ + for (; b_idx < edges; b_idx += step) { \ + out &= mask_dir; \ + if (!(mask_mv & b_idx)) { \ + if (bidir) { \ + ref2 = __lasx_xvldx(ref_t, d_idx_12); \ + ref3 = __lasx_xvldx(ref_t, d_idx_52); \ + ref0 = __lasx_xvld(ref_t, 12); \ + ref1 = __lasx_xvld(ref_t, 52); \ + ref2 = __lasx_xvilvl_w(ref3, ref2); \ + ref0 = __lasx_xvilvl_w(ref0, ref0); \ + ref1 = __lasx_xvilvl_w(ref1, ref1); \ + ref3 = __lasx_xvshuf4i_w(ref2, 0xB1); \ + ref0 = __lasx_xvsub_b(ref0, ref2); \ + ref1 = __lasx_xvsub_b(ref1, ref3); \ + ref0 = __lasx_xvor_v(ref0, ref1); \ +\ + tmp2 = __lasx_xvldx(mv_t, d_idx_x4_48); \ + tmp3 = __lasx_xvld(mv_t, 48); \ + tmp4 = __lasx_xvld(mv_t, 208); \ + tmp5 = __lasx_xvld(mv_t + d_idx_x4, 208); \ + DUP2_ARG3(__lasx_xvpermi_q, tmp2, tmp2, 0x20, tmp5, tmp5, \ + 0x20, tmp2, tmp5); \ + tmp3 = __lasx_xvpermi_q(tmp4, tmp3, 0x20); \ + tmp2 = __lasx_xvsub_h(tmp2, tmp3); \ + tmp5 = __lasx_xvsub_h(tmp5, tmp3); \ + DUP2_ARG2(__lasx_xvsat_h, tmp2, 7, tmp5, 7, tmp2, tmp5); \ + tmp0 = __lasx_xvpickev_b(tmp5, tmp2); \ + tmp0 = __lasx_xvpermi_d(tmp0, 0xd8); \ + tmp0 = __lasx_xvadd_b(tmp0, cnst_1); \ + tmp0 = __lasx_xvssub_bu(tmp0, cnst_0); \ + tmp0 = __lasx_xvsat_h(tmp0, 7); \ + tmp0 = __lasx_xvpickev_b(tmp0, tmp0); \ + tmp0 = __lasx_xvpermi_d(tmp0, 0xd8); \ + tmp1 = __lasx_xvpickod_d(tmp0, tmp0); \ + out = __lasx_xvor_v(ref0, tmp0); \ + tmp1 = __lasx_xvshuf4i_w(tmp1, 0xB1); \ + out = __lasx_xvor_v(out, tmp1); \ + tmp0 = __lasx_xvshuf4i_w(out, 0xB1); \ + out = __lasx_xvmin_bu(out, tmp0); \ + } else { \ + ref0 = __lasx_xvldx(ref_t, d_idx_12); \ + ref3 = __lasx_xvld(ref_t, 12); \ + tmp2 = __lasx_xvldx(mv_t, d_idx_x4_48); \ + tmp3 = __lasx_xvld(mv_t, 48); \ + tmp4 = __lasx_xvsub_h(tmp3, tmp2); \ + tmp1 = __lasx_xvsat_h(tmp4, 7); \ + tmp1 = __lasx_xvpickev_b(tmp1, tmp1); \ + tmp1 = __lasx_xvadd_b(tmp1, cnst_1); \ + out = __lasx_xvssub_bu(tmp1, cnst_0); \ + out = __lasx_xvsat_h(out, 7); \ + out = __lasx_xvpickev_b(out, out); \ + ref0 = __lasx_xvsub_b(ref3, ref0); \ + out = __lasx_xvor_v(out, ref0); \ + } \ + } \ + tmp0 = __lasx_xvld(nnz_t, 12); \ + tmp1 = __lasx_xvldx(nnz_t, d_idx_12); \ + tmp0 = __lasx_xvor_v(tmp0, tmp1); \ + tmp0 = __lasx_xvmin_bu(tmp0, cnst_2); \ + out = __lasx_xvmin_bu(out, cnst_2); \ + tmp0 = __lasx_xvslli_h(tmp0, 1); \ + tmp0 = __lasx_xvmax_bu(out, tmp0); \ + tmp0 = __lasx_vext2xv_hu_bu(tmp0); \ + __lasx_xvstelm_d(tmp0, bS_t + dir_x32, 0, 0); \ + ref_t += step; \ + mv_t += step_x4; \ + nnz_t += step; \ + bS_t += step; \ + } \ +} while(0) + +void ff_h264_loop_filter_strength_lasx(int16_t bS[2][4][4], uint8_t nnz[40], + int8_t ref[2][40], int16_t mv[2][40][2], + int bidir, int edges, int step, + int mask_mv0, int mask_mv1, int field) +{ + __m256i out; + __m256i ref0, ref1, ref2, ref3; + __m256i tmp0, tmp1; + __m256i tmp2, tmp3, tmp4, tmp5; + __m256i cnst_0, cnst_1, cnst_2; + __m256i zero = __lasx_xvldi(0); + __m256i one = __lasx_xvnor_v(zero, zero); + int64_t cnst3 = 0x0206020602060206, cnst4 = 0x0103010301030103; + if (field) { + cnst_0 = __lasx_xvreplgr2vr_d(cnst3); + cnst_1 = __lasx_xvreplgr2vr_d(cnst4); + cnst_2 = __lasx_xvldi(0x01); + } else { + DUP2_ARG1(__lasx_xvldi, 0x06, 0x03, cnst_0, cnst_1); + cnst_2 = __lasx_xvldi(0x01); + } + step <<= 3; + edges <<= 3; + + H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(edges, step, mask_mv1, + 1, -8, zero); + H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(32, 8, mask_mv0, 0, -1, one); + + DUP2_ARG2(__lasx_xvld, (int8_t*)bS, 0, (int8_t*)bS, 16, tmp0, tmp1); + DUP2_ARG2(__lasx_xvilvh_d, tmp0, tmp0, tmp1, tmp1, tmp2, tmp3); + LASX_TRANSPOSE4x4_H(tmp0, tmp2, tmp1, tmp3, tmp2, tmp3, tmp4, tmp5); + __lasx_xvstelm_d(tmp2, (int8_t*)bS, 0, 0); + __lasx_xvstelm_d(tmp3, (int8_t*)bS + 8, 0, 0); + __lasx_xvstelm_d(tmp4, (int8_t*)bS + 16, 0, 0); + __lasx_xvstelm_d(tmp5, (int8_t*)bS + 24, 0, 0); +} diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c index 0985c2fe8a..37633c3e51 100644 --- a/libavcodec/loongarch/h264dsp_init_loongarch.c +++ b/libavcodec/loongarch/h264dsp_init_loongarch.c @@ -29,6 +29,8 @@ av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, int cpu_flags = av_get_cpu_flags(); if (have_lasx(cpu_flags)) { + if (chroma_format_idc <= 1) + c->h264_loop_filter_strength = ff_h264_loop_filter_strength_lasx; if (bit_depth == 8) { c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_lasx; c->h264_add_pixels8_clear = ff_h264_add_pixels8_8_lasx; diff --git a/libavcodec/loongarch/h264dsp_lasx.h b/libavcodec/loongarch/h264dsp_lasx.h index bfd567fffa..4cf813750b 100644 --- a/libavcodec/loongarch/h264dsp_lasx.h +++ b/libavcodec/loongarch/h264dsp_lasx.h @@ -88,4 +88,10 @@ void ff_h264_idct_add16_intra_lasx(uint8_t *dst, const int32_t *blk_offset, const uint8_t nzc[15 * 8]); void ff_h264_deq_idct_luma_dc_lasx(int16_t *dst, int16_t *src, int32_t de_qval); + +void ff_h264_loop_filter_strength_lasx(int16_t bS[2][4][4], uint8_t nnz[40], + int8_t ref[2][40], int16_t mv[2][40][2], + int bidir, int edges, int step, + int mask_mv0, int mask_mv1, int field); + #endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H From df46d7cb49ce301d83c1d20cfc4ef47390d47691 Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Wed, 15 Dec 2021 11:51:10 +0800 Subject: [PATCH 479/894] avcodec: [loongarch] Optimize pred16x16_plane with LASX. ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:295 after :296 Change-Id: I281bc739f708d45f91fc3860150944c0b8a6a5ba Reviewed-by: Shiyou Yin Reviewed-by: guxiwei Signed-off-by: Michael Niedermayer --- libavcodec/h264pred.c | 2 + libavcodec/h264pred.h | 2 + libavcodec/loongarch/Makefile | 2 + .../loongarch/h264_intrapred_init_loongarch.c | 50 ++++++++ libavcodec/loongarch/h264_intrapred_lasx.c | 121 ++++++++++++++++++ libavcodec/loongarch/h264_intrapred_lasx.h | 31 +++++ 6 files changed, 208 insertions(+) create mode 100644 libavcodec/loongarch/h264_intrapred_init_loongarch.c create mode 100644 libavcodec/loongarch/h264_intrapred_lasx.c create mode 100644 libavcodec/loongarch/h264_intrapred_lasx.h diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index b0fec71f25..bd0d4a3d06 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -602,4 +602,6 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc); if (ARCH_MIPS) ff_h264_pred_init_mips(h, codec_id, bit_depth, chroma_format_idc); + if (ARCH_LOONGARCH) + ff_h264_pred_init_loongarch(h, codec_id, bit_depth, chroma_format_idc); } diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 2863dc9bd1..4583052dfe 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -122,5 +122,7 @@ void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); void ff_h264_pred_init_mips(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); +void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id, + const int bit_depth, const int chroma_format_idc); #endif /* AVCODEC_H264PRED_H */ diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 1e1fe3fd48..30799e4e48 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -1,8 +1,10 @@ OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_init_loongarch.o OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o +OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ loongarch/h264idct_lasx.o \ loongarch/h264_deblock_lasx.o +LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o diff --git a/libavcodec/loongarch/h264_intrapred_init_loongarch.c b/libavcodec/loongarch/h264_intrapred_init_loongarch.c new file mode 100644 index 0000000000..12620bd842 --- /dev/null +++ b/libavcodec/loongarch/h264_intrapred_init_loongarch.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/h264pred.h" +#include "h264_intrapred_lasx.h" + +av_cold void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id, + const int bit_depth, + const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (bit_depth == 8) { + if (have_lasx(cpu_flags)) { + if (chroma_format_idc <= 1) { + } + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { + } else { + if (chroma_format_idc <= 1) { + } + if (codec_id == AV_CODEC_ID_SVQ3) { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_svq3_8_lasx; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_rv40_8_lasx; + } else { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_h264_8_lasx; + } + } + } + } +} diff --git a/libavcodec/loongarch/h264_intrapred_lasx.c b/libavcodec/loongarch/h264_intrapred_lasx.c new file mode 100644 index 0000000000..c38cd611b8 --- /dev/null +++ b/libavcodec/loongarch/h264_intrapred_lasx.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "h264_intrapred_lasx.h" + +#define PRED16X16_PLANE \ + ptrdiff_t stride_1, stride_2, stride_3, stride_4, stride_5, stride_6; \ + ptrdiff_t stride_8, stride_15; \ + int32_t res0, res1, res2, res3, cnt; \ + uint8_t *src0, *src1; \ + __m256i reg0, reg1, reg2, reg3, reg4; \ + __m256i tmp0, tmp1, tmp2, tmp3; \ + __m256i shuff = {0x0B040A0509060807, 0x0F000E010D020C03, 0, 0}; \ + __m256i mult = {0x0004000300020001, 0x0008000700060005, 0, 0}; \ + __m256i int_mult1 = {0x0000000100000000, 0x0000000300000002, \ + 0x0000000500000004, 0x0000000700000006}; \ + \ + stride_1 = -stride; \ + stride_2 = stride << 1; \ + stride_3 = stride_2 + stride; \ + stride_4 = stride_2 << 1; \ + stride_5 = stride_4 + stride; \ + stride_6 = stride_3 << 1; \ + stride_8 = stride_4 << 1; \ + stride_15 = (stride_8 << 1) - stride; \ + src0 = src - 1; \ + src1 = src0 + stride_8; \ + \ + reg0 = __lasx_xvldx(src0, -stride); \ + reg1 = __lasx_xvldx(src, (8 - stride)); \ + reg0 = __lasx_xvilvl_d(reg1, reg0); \ + reg0 = __lasx_xvshuf_b(reg0, reg0, shuff); \ + reg0 = __lasx_xvhsubw_hu_bu(reg0, reg0); \ + reg0 = __lasx_xvmul_h(reg0, mult); \ + res1 = (src1[0] - src0[stride_6]) + \ + 2 * (src1[stride] - src0[stride_5]) + \ + 3 * (src1[stride_2] - src0[stride_4]) + \ + 4 * (src1[stride_3] - src0[stride_3]) + \ + 5 * (src1[stride_4] - src0[stride_2]) + \ + 6 * (src1[stride_5] - src0[stride]) + \ + 7 * (src1[stride_6] - src0[0]) + \ + 8 * (src0[stride_15] - src0[stride_1]); \ + reg0 = __lasx_xvhaddw_w_h(reg0, reg0); \ + reg0 = __lasx_xvhaddw_d_w(reg0, reg0); \ + reg0 = __lasx_xvhaddw_q_d(reg0, reg0); \ + res0 = __lasx_xvpickve2gr_w(reg0, 0); \ + +#define PRED16X16_PLANE_END \ + res2 = (src0[stride_15] + src[15 - stride] + 1) << 4; \ + res3 = 7 * (res0 + res1); \ + res2 -= res3; \ + reg0 = __lasx_xvreplgr2vr_w(res0); \ + reg1 = __lasx_xvreplgr2vr_w(res1); \ + reg2 = __lasx_xvreplgr2vr_w(res2); \ + reg3 = __lasx_xvmul_w(reg0, int_mult1); \ + reg4 = __lasx_xvslli_w(reg0, 3); \ + reg4 = __lasx_xvadd_w(reg4, reg3); \ + for (cnt = 8; cnt--;) { \ + tmp0 = __lasx_xvadd_w(reg2, reg3); \ + tmp1 = __lasx_xvadd_w(reg2, reg4); \ + tmp0 = __lasx_xvssrani_hu_w(tmp1, tmp0, 5); \ + tmp0 = __lasx_xvpermi_d(tmp0, 0xD8); \ + reg2 = __lasx_xvadd_w(reg2, reg1); \ + tmp2 = __lasx_xvadd_w(reg2, reg3); \ + tmp3 = __lasx_xvadd_w(reg2, reg4); \ + tmp1 = __lasx_xvssrani_hu_w(tmp3, tmp2, 5); \ + tmp1 = __lasx_xvpermi_d(tmp1, 0xD8); \ + tmp0 = __lasx_xvssrani_bu_h(tmp1, tmp0, 0); \ + reg2 = __lasx_xvadd_w(reg2, reg1); \ + __lasx_xvstelm_d(tmp0, src, 0, 0); \ + __lasx_xvstelm_d(tmp0, src, 8, 2); \ + src += stride; \ + __lasx_xvstelm_d(tmp0, src, 0, 1); \ + __lasx_xvstelm_d(tmp0, src, 8, 3); \ + src += stride; \ + } + + +void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride) +{ + PRED16X16_PLANE + res0 = (5 * res0 + 32) >> 6; + res1 = (5 * res1 + 32) >> 6; + PRED16X16_PLANE_END +} + +void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride) +{ + PRED16X16_PLANE + res0 = (res0 + (res0 >> 2)) >> 4; + res1 = (res1 + (res1 >> 2)) >> 4; + PRED16X16_PLANE_END +} + +void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride) +{ + PRED16X16_PLANE + cnt = (5 * (res0/4)) / 16; + res0 = (5 * (res1/4)) / 16; + res1 = cnt; + PRED16X16_PLANE_END +} diff --git a/libavcodec/loongarch/h264_intrapred_lasx.h b/libavcodec/loongarch/h264_intrapred_lasx.h new file mode 100644 index 0000000000..0c2653300c --- /dev/null +++ b/libavcodec/loongarch/h264_intrapred_lasx.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H +#define AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H + +#include "libavcodec/avcodec.h" + +void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride); +void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride); +void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride); + +#endif // #ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H From 5317a6366f23f725007a06e695126232173417ab Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 14 Dec 2021 14:43:33 +0100 Subject: [PATCH 480/894] vf_libplacebo: switch to newer libplacebo helpers Support for mapping/unmapping hardware frames has been added into libplacebo itself, so we can scrap this code in favor of using the new functions. This has the additional benefit of being forwards-compatible as support for more complicated frame-related state management is added to libplacebo (e.g. mapping dolby vision metadata). It's worth pointing out that, technically, this would also allow `vf_libplacebo` to accept, practically unmodified, other frame types (e.g. vaapi or drm), or even software input formats. (Although we still need a vulkan *device* to be available) To keep things simple, though, retain the current restriction to vulkan frames. It's possible we could rethink this in a future commit, but for now I don't want to introduce any more potentially breaking changes. --- configure | 2 +- libavfilter/vf_libplacebo.c | 91 +++++-------------------------------- 2 files changed, 13 insertions(+), 80 deletions(-) diff --git a/configure b/configure index c4afde4c5c..5fffcb8afe 100755 --- a/configure +++ b/configure @@ -6566,7 +6566,7 @@ enabled libopus && { require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create } } -enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.173.0" libplacebo/vulkan.h pl_vulkan_create +enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.184.0" libplacebo/vulkan.h pl_vulkan_create enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection enabled librav1e && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index e2749857d1..7ece9d829e 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -275,64 +275,18 @@ static void libplacebo_uninit(AVFilterContext *avctx) s->gpu = NULL; } -static int wrap_vkframe(pl_gpu gpu, const AVFrame *frame, int plane, pl_tex *tex) -{ - AVVkFrame *vkf = (AVVkFrame *) frame->data[0]; - const AVHWFramesContext *hwfc = (AVHWFramesContext *) frame->hw_frames_ctx->data; - const AVVulkanFramesContext *vkfc = hwfc->hwctx; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); - const VkFormat *vk_fmt = av_vkfmt_from_pixfmt(hwfc->sw_format); - const int chroma = plane == 1 || plane == 2; - - *tex = pl_vulkan_wrap(gpu, pl_vulkan_wrap_params( - .image = vkf->img[plane], - .format = vk_fmt[plane], - .width = AV_CEIL_RSHIFT(frame->width, chroma ? desc->log2_chroma_w : 0), - .height = AV_CEIL_RSHIFT(frame->height, chroma ? desc->log2_chroma_h : 0), - .usage = vkfc->usage, - )); - - if (!*tex) - return AVERROR(ENOMEM); - - pl_vulkan_release(gpu, *tex, vkf->layout[plane], (pl_vulkan_sem) { - .sem = vkf->sem[plane], - .value = vkf->sem_value[plane] - }); - return 0; -} - -static int unwrap_vkframe(pl_gpu gpu, AVFrame *frame, int plane, pl_tex *tex) -{ - AVVkFrame *vkf = (AVVkFrame *) frame->data[0]; - int ok = pl_vulkan_hold_raw(gpu, *tex, &vkf->layout[plane], - (pl_vulkan_sem) { vkf->sem[plane], vkf->sem_value[plane] + 1 }); - vkf->access[plane] = 0; - vkf->sem_value[plane] += !!ok; - return ok ? 0 : AVERROR_EXTERNAL; -} - -static void set_sample_depth(struct pl_frame *out_frame, const AVFrame *frame) -{ - const AVHWFramesContext *hwfc = (AVHWFramesContext *) frame->hw_frames_ctx->data; - pl_fmt fmt = out_frame->planes[0].texture->params.format; - struct pl_bit_encoding *bits = &out_frame->repr.bits; - bits->sample_depth = fmt->component_depth[0]; - - switch (hwfc->sw_format) { - case AV_PIX_FMT_P010: bits->bit_shift = 6; break; - default: break; - } -} - static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) { - int err = 0; + int err = 0, ok; LibplaceboContext *s = avctx->priv; struct pl_render_params params; struct pl_frame image, target; - pl_frame_from_avframe(&image, in); - pl_frame_from_avframe(&target, out); + ok = pl_map_avframe(s->gpu, &image, NULL, in); + ok &= pl_map_avframe(s->gpu, &target, NULL, out); + if (!ok) { + err = AVERROR_EXTERNAL; + goto fail; + } if (!s->apply_filmgrain) image.film_grain.type = PL_FILM_GRAIN_NONE; @@ -411,38 +365,17 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) RET(find_scaler(avctx, ¶ms.upscaler, s->upscaler)); RET(find_scaler(avctx, ¶ms.downscaler, s->downscaler)); - /* Ideally, we would persistently wrap all of these AVVkFrames into pl_tex - * objects, but for now we'll just create and destroy a wrapper per frame. - * Note that doing it this way is suboptimal, since it results in the - * creation and destruction of a VkSampler and VkFramebuffer per frame. - * - * FIXME: Can we do better? */ - for (int i = 0; i < image.num_planes; i++) - RET(wrap_vkframe(s->gpu, in, i, &image.planes[i].texture)); - for (int i = 0; i < target.num_planes; i++) - RET(wrap_vkframe(s->gpu, out, i, &target.planes[i].texture)); - - /* Since we-re mapping vkframes manually, the pl_frame helpers don't know - * about the mismatch between the sample format and the color depth. */ - set_sample_depth(&image, in); - set_sample_depth(&target, out); - pl_render_image(s->renderer, &image, &target, ¶ms); - - for (int i = 0; i < image.num_planes; i++) - RET(unwrap_vkframe(s->gpu, in, i, &image.planes[i].texture)); - for (int i = 0; i < target.num_planes; i++) - RET(unwrap_vkframe(s->gpu, out, i, &target.planes[i].texture)); + pl_unmap_avframe(s->gpu, &image); + pl_unmap_avframe(s->gpu, &target); /* Flush the command queues for performance */ pl_gpu_flush(s->gpu); + return 0; - /* fall through */ fail: - for (int i = 0; i < image.num_planes; i++) - pl_tex_destroy(s->gpu, &image.planes[i].texture); - for (int i = 0; i < target.num_planes; i++) - pl_tex_destroy(s->gpu, &target.planes[i].texture); + pl_unmap_avframe(s->gpu, &image); + pl_unmap_avframe(s->gpu, &target); return err; } From e9ba40c5c9a49bc97d16d66c46ff993fa84a6c31 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 15 Dec 2021 22:32:15 +0100 Subject: [PATCH 481/894] lavfi/vf_libplacebo: update deprecated option name This was renamed upstream quite a while ago (v3.112.0). Rename the option name as well for consistency (and expand the description just slightly). Signed-off-by: Niklas Haas --- libavfilter/vf_libplacebo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 7ece9d829e..5b1e7b5285 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -62,7 +62,7 @@ typedef struct LibplaceboContext { float polar_cutoff; int disable_linear; int disable_builtin; - int force_3dlut; + int force_icc_lut; int force_dither; int disable_fbos; @@ -357,7 +357,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) .polar_cutoff = s->polar_cutoff, .disable_linear_scaling = s->disable_linear, .disable_builtin_scalers = s->disable_builtin, - .force_3dlut = s->force_3dlut, + .force_icc_lut = s->force_icc_lut, .force_dither = s->force_dither, .disable_fbos = s->disable_fbos, }; @@ -623,7 +623,7 @@ static const AVOption libplacebo_options[] = { { "polar_cutoff", "Polar LUT cutoff", OFFSET(polar_cutoff), AV_OPT_TYPE_FLOAT, {.i64 = 0}, 0.0, 1.0, DYNAMIC }, { "disable_linear", "Disable linear scaling", OFFSET(disable_linear), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "disable_builtin", "Disable built-in scalers", OFFSET(disable_builtin), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, - { "force_3dlut", "Force the use of a full 3DLUT", OFFSET(force_3dlut), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "force_icc_lut", "Force the use of a full ICC 3DLUT for color mapping", OFFSET(force_icc_lut), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "force_dither", "Force dithering", OFFSET(force_dither), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "disable_fbos", "Force-disable FBOs", OFFSET(disable_fbos), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { NULL }, From f900a19fa94b1a55b660ec2e5c13419d59754bc0 Mon Sep 17 00:00:00 2001 From: Alan Kelly Date: Wed, 15 Dec 2021 10:35:02 +0100 Subject: [PATCH 482/894] libswscale: Adds ff_hscale8to15_4_avx2 and ff_hscale8to15_X4_avx2 for all filter sizes. Fixes so that fate under 64 bit Windows passes. These functions replace all ff_hscale8to15_*_ssse3 when avx2 is available. Signed-off-by: James Almer --- libswscale/swscale_internal.h | 2 + libswscale/utils.c | 37 +++++++++++ libswscale/x86/Makefile | 1 + libswscale/x86/scale_avx2.asm | 112 ++++++++++++++++++++++++++++++++++ libswscale/x86/swscale.c | 19 ++++++ tests/checkasm/sw_scale.c | 20 ++++-- 6 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 libswscale/x86/scale_avx2.asm diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 708facba67..64aa0b9804 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -1105,4 +1105,6 @@ void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, //number of extra lines to process #define MAX_LINES_AHEAD 4 +//shuffle filter and filterPos for hyScale and hcScale filters in avx2 +void ff_shuffle_filter_coefficients(SwsContext *c, int* filterPos, int filterSize, int16_t *filter, int dstW); #endif /* SWSCALE_SWSCALE_INTERNAL_H */ diff --git a/libswscale/utils.c b/libswscale/utils.c index ae92ac9fbc..d4a72d3ce1 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -278,6 +278,41 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_P416LE] = { 1, 0 }, }; +void ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos, int filterSize, int16_t *filter, int dstW){ +#if ARCH_X86_64 + int i, j, k, l; + int cpu_flags = av_get_cpu_flags(); + if (EXTERNAL_AVX2_FAST(cpu_flags)){ + if ((c->srcBpc == 8) && (c->dstBpc <= 14)){ + if (dstW % 16 == 0){ + if (filter != NULL){ + for (i = 0; i < dstW; i += 8){ + FFSWAP(int, filterPos[i + 2], filterPos[i+4]); + FFSWAP(int, filterPos[i + 3], filterPos[i+5]); + } + if (filterSize > 4){ + int16_t *tmp2 = av_malloc(dstW * filterSize * 2); + memcpy(tmp2, filter, dstW * filterSize * 2); + for (i = 0; i < dstW; i += 16){//pixel + for (k = 0; k < filterSize / 4; ++k){//fcoeff + for (j = 0; j < 16; ++j){//inner pixel + for (l = 0; l < 4; ++l){//coeff + int from = i * filterSize + j * filterSize + k * 4 + l; + int to = (i) * filterSize + j * 4 + l + k * 64; + filter[to] = tmp2[from]; + } + } + } + } + av_free(tmp2); + } + } + } + } + } +#endif +} + int sws_isSupportedInput(enum AVPixelFormat pix_fmt) { return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? @@ -1801,6 +1836,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, get_local_pos(c, 0, 0, 0), get_local_pos(c, 0, 0, 0))) < 0) goto fail; + ff_shuffle_filter_coefficients(c, c->hLumFilterPos, c->hLumFilterSize, c->hLumFilter, dstW); if ((ret = initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc, c->chrSrcW, c->chrDstW, filterAlign, 1 << 14, @@ -1810,6 +1846,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0), get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0))) < 0) goto fail; + ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW); } } // initialize horizontal stuff diff --git a/libswscale/x86/Makefile b/libswscale/x86/Makefile index bfe383364e..68391494be 100644 --- a/libswscale/x86/Makefile +++ b/libswscale/x86/Makefile @@ -11,6 +11,7 @@ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o X86ASM-OBJS += x86/input.o \ x86/output.o \ x86/scale.o \ + x86/scale_avx2.o \ x86/rgb_2_rgb.o \ x86/yuv_2_rgb.o \ x86/yuv2yuvX.o \ diff --git a/libswscale/x86/scale_avx2.asm b/libswscale/x86/scale_avx2.asm new file mode 100644 index 0000000000..4e4fe5d794 --- /dev/null +++ b/libswscale/x86/scale_avx2.asm @@ -0,0 +1,112 @@ +;****************************************************************************** +;* x86-optimized horizontal line scaling functions +;* Copyright 2020 Google LLC +;* Copyright (c) 2011 Ronald S. Bultje +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +swizzle: dd 0, 4, 1, 5, 2, 6, 3, 7 +four: times 8 dd 4 + +SECTION .text + +;----------------------------------------------------------------------------- +; horizontal line scaling +; +; void hscale8to15__ +; (SwsContext *c, int16_t *dst, +; int dstW, const uint8_t *src, +; const int16_t *filter, +; const int32_t *filterPos, int filterSize); +; +; Scale one horizontal line. Input is 8-bit width Filter is 14 bits. Output is +; 15 bits (in int16_t). Each output pixel is generated from $filterSize input +; pixels, the position of the first pixel is given in filterPos[nOutputPixel]. +;----------------------------------------------------------------------------- + +%macro SCALE_FUNC 1 +cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, count, inner + pxor m0, m0 + mova m15, [swizzle] + mov countq, $0 + movsxd wq, wd +%ifidn %1, X4 + mova m14, [four] + shr fltsized, 2 +%endif +.loop: + movu m1, [fltposq] + movu m2, [fltposq+32] +%ifidn %1, X4 + pxor m9, m9 + pxor m10, m10 + pxor m11, m11 + pxor m12, m12 + mov innerq, $0 +.innerloop: +%endif + vpcmpeqd m13, m13 + vpgatherdd m3,[srcmemq + m1], m13 + vpcmpeqd m13, m13 + vpgatherdd m4,[srcmemq + m2], m13 + vpunpcklbw m5, m3, m0 + vpunpckhbw m6, m3, m0 + vpunpcklbw m7, m4, m0 + vpunpckhbw m8, m4, m0 + vpmaddwd m5, m5, [filterq] + vpmaddwd m6, m6, [filterq + 32] + vpmaddwd m7, m7, [filterq + 64] + vpmaddwd m8, m8, [filterq + 96] + add filterq, $80 +%ifidn %1, X4 + paddd m9, m5 + paddd m10, m6 + paddd m11, m7 + paddd m12, m8 + paddd m1, m14 + paddd m2, m14 + add innerq, $1 + cmp innerq, fltsizeq + jl .innerloop + vphaddd m5, m9, m10 + vphaddd m6, m11, m12 +%else + vphaddd m5, m5, m6 + vphaddd m6, m7, m8 +%endif + vpsrad m5, 7 + vpsrad m6, 7 + vpackssdw m5, m5, m6 + vpermd m5, m15, m5 + vmovdqu [dstq + countq * 2], m5 + add fltposq, $40 + add countq, $10 + cmp countq, wq + jl .loop +REP_RET +%endmacro + +%if ARCH_X86_64 +INIT_YMM avx2 +SCALE_FUNC 4 +SCALE_FUNC X4 +%endif diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index 0848a31461..164b06d6ba 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -276,6 +276,9 @@ SCALE_FUNCS_SSE(sse2); SCALE_FUNCS_SSE(ssse3); SCALE_FUNCS_SSE(sse4); +SCALE_FUNC(4, 8, 15, avx2); +SCALE_FUNC(X4, 8, 15, avx2); + #define VSCALEX_FUNC(size, opt) \ void ff_yuv2planeX_ ## size ## _ ## opt(const int16_t *filter, int filterSize, \ const int16_t **src, uint8_t *dest, int dstW, \ @@ -568,6 +571,22 @@ switch(c->dstBpc){ \ } #if ARCH_X86_64 +#define ASSIGN_AVX2_SCALE_FUNC(hscalefn, filtersize) \ + switch (filtersize) { \ + case 4: hscalefn = ff_hscale8to15_4_avx2; break; \ + default: hscalefn = ff_hscale8to15_X4_avx2; break; \ + break; \ + } + + if (EXTERNAL_AVX2_FAST(cpu_flags)){ + if ((c->srcBpc == 8) && (c->dstBpc <= 14)){ + if(c->chrDstW % 16 == 0) + ASSIGN_AVX2_SCALE_FUNC(c->hcScale, c->hChrFilterSize); + if(c->dstW % 16 == 0) + ASSIGN_AVX2_SCALE_FUNC(c->hyScale, c->hLumFilterSize); + } + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { switch (c->dstFormat) { case AV_PIX_FMT_NV12: diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index 1e7ffe0fff..011cb46428 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -134,13 +134,13 @@ static void check_yuv2yuvX(void) } #undef SRC_PIXELS -#define SRC_PIXELS 128 +#define SRC_PIXELS 512 static void check_hscale(void) { #define MAX_FILTER_WIDTH 40 -#define FILTER_SIZES 5 - static const int filter_sizes[FILTER_SIZES] = { 4, 8, 16, 32, 40 }; +#define FILTER_SIZES 6 + static const int filter_sizes[FILTER_SIZES] = { 4, 8, 12, 16, 32, 40 }; #define HSCALE_PAIRS 2 static const int hscale_pairs[HSCALE_PAIRS][2] = { @@ -159,6 +159,8 @@ static void check_hscale(void) // padded LOCAL_ALIGNED_32(int16_t, filter, [SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH]); LOCAL_ALIGNED_32(int32_t, filterPos, [SRC_PIXELS]); + LOCAL_ALIGNED_32(int16_t, filterAvx2, [SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH]); + LOCAL_ALIGNED_32(int32_t, filterPosAvx, [SRC_PIXELS]); // The dst parameter here is either int16_t or int32_t but we use void* to // just cover both cases. @@ -166,6 +168,8 @@ static void check_hscale(void) const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize); + int cpu_flags = av_get_cpu_flags(); + ctx = sws_alloc_context(); if (sws_init_context(ctx, NULL, NULL) < 0) fail(); @@ -179,9 +183,11 @@ static void check_hscale(void) ctx->srcBpc = hscale_pairs[hpi][0]; ctx->dstBpc = hscale_pairs[hpi][1]; ctx->hLumFilterSize = ctx->hChrFilterSize = width; + ctx->dstW = ctx->chrDstW = SRC_PIXELS; for (i = 0; i < SRC_PIXELS; i++) { filterPos[i] = i; + filterPosAvx[i] = i; // These filter cofficients are chosen to try break two corner // cases, namely: @@ -210,16 +216,20 @@ static void check_hscale(void) filter[SRC_PIXELS * width + i] = rnd(); } ff_sws_init_scale(ctx); + memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); + if (cpu_flags & AV_CPU_FLAG_AVX2){ + ff_shuffle_filter_coefficients(ctx, filterPosAvx, width, filterAvx2, SRC_PIXELS); + } if (check_func(ctx->hcScale, "hscale_%d_to_%d_width%d", ctx->srcBpc, ctx->dstBpc + 1, width)) { memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0])); memset(dst1, 0, SRC_PIXELS * sizeof(dst1[0])); call_ref(NULL, dst0, SRC_PIXELS, src, filter, filterPos, width); - call_new(NULL, dst1, SRC_PIXELS, src, filter, filterPos, width); + call_new(NULL, dst1, SRC_PIXELS, src, filterAvx2, filterPosAvx, width); if (memcmp(dst0, dst1, SRC_PIXELS * sizeof(dst0[0]))) fail(); - bench_new(NULL, dst0, SRC_PIXELS, src, filter, filterPos, width); + bench_new(NULL, dst0, SRC_PIXELS, src, filter, filterPosAvx, width); } } } From c22a9ece2e7d823507b81e7fe7789545f01e7c88 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 11 Dec 2021 15:24:00 +0100 Subject: [PATCH 483/894] avcodec/h2645_parse: Remove H2645NAL.rbsp_buffer Forgotten in 03b82b3ab9883cef017e513c7d0b3b986b3b3e7b. (Moving data to the front is only done to make existing initializations like H2645NAL nal = { NULL } not emit int->pointer conversion warnings.) Signed-off-by: Andreas Rheinhardt --- libavcodec/h2645_parse.c | 3 +-- libavcodec/h2645_parse.h | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 6fbe97ad4a..03780680c6 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -92,8 +92,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, } else if (i > length) i = length; - nal->rbsp_buffer = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size]; - dst = nal->rbsp_buffer; + dst = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size]; memcpy(dst, src, i); si = di = i; diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index 20a9d355f2..3a13ba248a 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -32,10 +32,8 @@ #define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytes typedef struct H2645NAL { - uint8_t *rbsp_buffer; - - int size; const uint8_t *data; + int size; /** * Size, in bits, of just the data, excluding the stop bit and any trailing From aba4a4f080b2c0aa96409f93f455f9870fabbe2d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 11 Dec 2021 15:35:03 +0100 Subject: [PATCH 484/894] avcodec/h2645_parse: Move ref_idc further up in H2645NAL This puts it directly near the NALU type which is more natural and furthermore reduces the size of the structure because it can be placed in padding (on 64-bit systems). Signed-off-by: Andreas Rheinhardt --- libavcodec/h2645_parse.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index 3a13ba248a..787ce971ee 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -51,6 +51,11 @@ typedef struct H2645NAL { */ int type; + /** + * H.264 only, nal_ref_idc + */ + int ref_idc; + /** * HEVC only, nuh_temporal_id_plus_1 - 1 */ @@ -64,10 +69,6 @@ typedef struct H2645NAL { int skipped_bytes; int skipped_bytes_pos_size; int *skipped_bytes_pos; - /** - * H.264 only, nal_ref_idc - */ - int ref_idc; } H2645NAL; typedef struct H2645RBSP { From 52a4d4404409af79ae0f5ed32d78386d43b19c84 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 9 Dec 2021 17:14:50 +0100 Subject: [PATCH 485/894] avformat/demux: Remove fake-loop When flushing, try_decode_frame() itself loops until the desired properties have been found or the decoder is drained. Signed-off-by: Andreas Rheinhardt --- libavformat/demux.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libavformat/demux.c b/libavformat/demux.c index 745dc8687c..87dbd53a0f 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2771,11 +2771,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) /* flush the decoders */ if (sti->info->found_decoder == 1) { - do { - err = try_decode_frame(ic, st, empty_pkt, - (options && i < orig_nb_streams) - ? &options[i] : NULL); - } while (err > 0 && !has_codec_parameters(st, NULL)); + err = try_decode_frame(ic, st, empty_pkt, + (options && i < orig_nb_streams) + ? &options[i] : NULL); if (err < 0) { av_log(ic, AV_LOG_INFO, From 97e26937b46323fc85480d32123d5d4f1fcd7832 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 9 Dec 2021 18:39:47 +0100 Subject: [PATCH 486/894] avformat/demux: Remove redundant prevention against infinite loop This piece of code has been added as FFmpeg's answer to infinite loops in try_decode_frame() in commit 6072a19b4f311cb172d45e90daad90824e40e4b6. There is no loop around try_decode_frame() any more, so this code can be removed. This code is only triggered in case a) the codec parameter could not be determined, b) the decode delay could not be guessed or c) no packet was ever encountered and the encoder has the AV_CODEC_CAP_CHANNEL_CONF. In these cases the new code will no longer emit a "decoding for stream %d failed" message, which is prima facie false. In case a) an additional "Could not find codec parameters" message is (and will be) emitted. No warning will be emitted any more in case b) (this happens e.g. with some h264-conformance FATE-files). Signed-off-by: Andreas Rheinhardt --- libavformat/demux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavformat/demux.c b/libavformat/demux.c index 87dbd53a0f..3f35b3860e 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2054,9 +2054,6 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, } } - if (!pkt.data && !got_picture) - ret = -1; - fail: if (do_skip_frame) { avctx->skip_frame = skip_frame; From 200a3728373fbc74cbfdfcbb3d2152cf21d17034 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 16:10:06 +0100 Subject: [PATCH 487/894] avcodec/pgssubdec: Always return error upon allocation error Signed-off-by: Andreas Rheinhardt --- libavcodec/pgssubdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 388639a110..2d5700a51e 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -677,7 +677,8 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, ret = AVERROR_INVALIDDATA; break; } - if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) { + if (ret < 0 && (ret == AVERROR(ENOMEM) || + avctx->err_recognition & AV_EF_EXPLODE)) { avsubtitle_free(data); *got_sub_ptr = 0; return ret; From 58228ab9b91a6a6e418fd38942aa84b6fffa7df9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 21:02:47 +0100 Subject: [PATCH 488/894] avcodec/pgssubdec: Remove redundant freeing code The caller of display_end_segment() frees the AVSubtitle on error in case ENOMEM is returned or err_recognition is set to explode, so display_end_segment() doesn't have to. Signed-off-by: Andreas Rheinhardt --- libavcodec/pgssubdec.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 2d5700a51e..d2824f5bbf 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -534,10 +534,8 @@ static int display_end_segment(AVCodecContext *avctx, void *data, PGSSubObject *object; sub->rects[i] = av_mallocz(sizeof(*sub->rects[0])); - if (!sub->rects[i]) { - avsubtitle_free(sub); + if (!sub->rects[i]) return AVERROR(ENOMEM); - } sub->num_rects++; sub->rects[i]->type = SUBTITLE_BITMAP; @@ -547,10 +545,8 @@ static int display_end_segment(AVCodecContext *avctx, void *data, // Missing object. Should only happen with damaged streams. av_log(avctx, AV_LOG_ERROR, "Invalid object id %d\n", ctx->presentation.objects[i].id); - if (avctx->err_recognition & AV_EF_EXPLODE) { - avsubtitle_free(sub); + if (avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; - } // Leaves rect empty with 0 width and height. continue; } @@ -569,16 +565,13 @@ static int display_end_segment(AVCodecContext *avctx, void *data, if (object->rle_remaining_len) { av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", object->rle_data_len, object->rle_remaining_len); - if (avctx->err_recognition & AV_EF_EXPLODE) { - avsubtitle_free(sub); + if (avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; - } } ret = decode_rle(avctx, sub->rects[i], object->rle, object->rle_data_len); if (ret < 0) { if ((avctx->err_recognition & AV_EF_EXPLODE) || ret == AVERROR(ENOMEM)) { - avsubtitle_free(sub); return ret; } sub->rects[i]->w = 0; @@ -589,10 +582,8 @@ static int display_end_segment(AVCodecContext *avctx, void *data, /* Allocate memory for colors */ sub->rects[i]->nb_colors = 256; sub->rects[i]->data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[i]->data[1]) { - avsubtitle_free(sub); + if (!sub->rects[i]->data[1]) return AVERROR(ENOMEM); - } if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40) memcpy(sub->rects[i]->data[1], palette->clut, sub->rects[i]->nb_colors * sizeof(uint32_t)); From d59f454ed2ba4cc89533a84d727eef9aaaed635d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 11 Dec 2021 18:16:45 +0100 Subject: [PATCH 489/894] avcodec/pgssubdec: Use dedicated pointer for accesses Improves readability and decreases codesize. Signed-off-by: Andreas Rheinhardt --- libavcodec/pgssubdec.c | 66 ++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index d2824f5bbf..8a200aa01b 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -443,6 +443,7 @@ static int parse_presentation_segment(AVCodecContext *avctx, for (i = 0; i < ctx->presentation.object_count; i++) { + PGSSubObjectRef *const object = &ctx->presentation.objects[i]; if (buf_end - buf < 8) { av_log(avctx, AV_LOG_ERROR, "Insufficent space for object\n"); @@ -450,32 +451,29 @@ static int parse_presentation_segment(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - ctx->presentation.objects[i].id = bytestream_get_be16(&buf); - ctx->presentation.objects[i].window_id = bytestream_get_byte(&buf); - ctx->presentation.objects[i].composition_flag = bytestream_get_byte(&buf); + object->id = bytestream_get_be16(&buf); + object->window_id = bytestream_get_byte(&buf); + object->composition_flag = bytestream_get_byte(&buf); - ctx->presentation.objects[i].x = bytestream_get_be16(&buf); - ctx->presentation.objects[i].y = bytestream_get_be16(&buf); + object->x = bytestream_get_be16(&buf); + object->y = bytestream_get_be16(&buf); // If cropping - if (ctx->presentation.objects[i].composition_flag & 0x80) { - ctx->presentation.objects[i].crop_x = bytestream_get_be16(&buf); - ctx->presentation.objects[i].crop_y = bytestream_get_be16(&buf); - ctx->presentation.objects[i].crop_w = bytestream_get_be16(&buf); - ctx->presentation.objects[i].crop_h = bytestream_get_be16(&buf); + if (object->composition_flag & 0x80) { + object->crop_x = bytestream_get_be16(&buf); + object->crop_y = bytestream_get_be16(&buf); + object->crop_w = bytestream_get_be16(&buf); + object->crop_h = bytestream_get_be16(&buf); } ff_dlog(avctx, "Subtitle Placement x=%d, y=%d\n", - ctx->presentation.objects[i].x, ctx->presentation.objects[i].y); + object->x, object->y); - if (ctx->presentation.objects[i].x > avctx->width || - ctx->presentation.objects[i].y > avctx->height) { + if (object->x > avctx->width || object->y > avctx->height) { av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", - ctx->presentation.objects[i].x, - ctx->presentation.objects[i].y, + object->x, object->y, avctx->width, avctx->height); - ctx->presentation.objects[i].x = 0; - ctx->presentation.objects[i].y = 0; + object->y = object->x = 0; if (avctx->err_recognition & AV_EF_EXPLODE) { return AVERROR_INVALIDDATA; } @@ -531,13 +529,13 @@ static int display_end_segment(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } for (i = 0; i < ctx->presentation.object_count; i++) { + AVSubtitleRect *const rect = av_mallocz(sizeof(*rect)); PGSSubObject *object; - sub->rects[i] = av_mallocz(sizeof(*sub->rects[0])); - if (!sub->rects[i]) + if (!rect) return AVERROR(ENOMEM); - sub->num_rects++; - sub->rects[i]->type = SUBTITLE_BITMAP; + sub->rects[sub->num_rects++] = rect; + rect->type = SUBTITLE_BITMAP; /* Process bitmap */ object = find_object(ctx->presentation.objects[i].id, &ctx->objects); @@ -551,16 +549,16 @@ static int display_end_segment(AVCodecContext *avctx, void *data, continue; } if (ctx->presentation.objects[i].composition_flag & 0x40) - sub->rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED; + rect->flags |= AV_SUBTITLE_FLAG_FORCED; - sub->rects[i]->x = ctx->presentation.objects[i].x; - sub->rects[i]->y = ctx->presentation.objects[i].y; + rect->x = ctx->presentation.objects[i].x; + rect->y = ctx->presentation.objects[i].y; if (object->rle) { - sub->rects[i]->w = object->w; - sub->rects[i]->h = object->h; + rect->w = object->w; + rect->h = object->h; - sub->rects[i]->linesize[0] = object->w; + rect->linesize[0] = object->w; if (object->rle_remaining_len) { av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", @@ -568,25 +566,25 @@ static int display_end_segment(AVCodecContext *avctx, void *data, if (avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; } - ret = decode_rle(avctx, sub->rects[i], object->rle, object->rle_data_len); + ret = decode_rle(avctx, rect, object->rle, object->rle_data_len); if (ret < 0) { if ((avctx->err_recognition & AV_EF_EXPLODE) || ret == AVERROR(ENOMEM)) { return ret; } - sub->rects[i]->w = 0; - sub->rects[i]->h = 0; + rect->w = 0; + rect->h = 0; continue; } } /* Allocate memory for colors */ - sub->rects[i]->nb_colors = 256; - sub->rects[i]->data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[i]->data[1]) + rect->nb_colors = 256; + rect->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!rect->data[1]) return AVERROR(ENOMEM); if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40) - memcpy(sub->rects[i]->data[1], palette->clut, sub->rects[i]->nb_colors * sizeof(uint32_t)); + memcpy(rect->data[1], palette->clut, rect->nb_colors * sizeof(uint32_t)); } return 1; } From cee04cbfe1bf77db5a5bb4ade786573f08a586fc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 22:05:20 +0100 Subject: [PATCH 490/894] avcodec/decode: Fix leaks upon subtitle decoding errors Up until now, various subtitle decoders have not cleaned up the AVSubtitle on error; this task must not be left to the user because the documentation explicitly states that the AVSubtitle "must be freed with avsubtitle_free if *got_sub_ptr is set" (which it isn't on error). Leaks happen upon failure in ff_ass_add_rect() or in ass_decode_frame(); freeing generically also allows to remove now redundant freeing code in pgssubdec and dvbsubdec. While just at it, also reset got_sub_ptr generically on error. Signed-off-by: Andreas Rheinhardt --- libavcodec/decode.c | 13 ++++++++----- libavcodec/dvbsubdec.c | 2 -- libavcodec/pgssubdec.c | 5 +---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 52bf5dcd33..afe2c0c3c1 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -834,8 +834,14 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, sub->pts = av_rescale_q(avpkt->pts, avctx->pkt_timebase, AV_TIME_BASE_Q); ret = avctx->codec->decode(avctx, sub, got_sub_ptr, pkt); - av_assert1((ret >= 0) >= !!*got_sub_ptr && - !!*got_sub_ptr >= !!sub->num_rects); + if (pkt == avci->buffer_pkt) // did we recode? + av_packet_unref(avci->buffer_pkt); + if (ret < 0) { + *got_sub_ptr = 0; + avsubtitle_free(sub); + return ret; + } + av_assert1(!sub->num_rects || *got_sub_ptr); if (sub->num_rects && !sub->end_display_time && avpkt->duration && avctx->pkt_timebase.num) { @@ -863,9 +869,6 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, if (*got_sub_ptr) avctx->frame_number++; - - if (pkt == avci->buffer_pkt) // did we recode? - av_packet_unref(avci->buffer_pkt); } return ret; diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 81ccaf4c57..bc741a1de6 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -1715,8 +1715,6 @@ static int dvbsub_decode(AVCodecContext *avctx, end: if (ret < 0) { - *got_sub_ptr = 0; - avsubtitle_free(sub); return ret; } else { if (ctx->compute_edt == 1) diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 8a200aa01b..bdd20c914b 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -667,11 +667,8 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, break; } if (ret < 0 && (ret == AVERROR(ENOMEM) || - avctx->err_recognition & AV_EF_EXPLODE)) { - avsubtitle_free(data); - *got_sub_ptr = 0; + avctx->err_recognition & AV_EF_EXPLODE)) return ret; - } buf += segment_length; } From 2adbb0c2af2cc42a25ab58ef0d4837245f0fbf62 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 22:42:24 +0100 Subject: [PATCH 491/894] avcodec/ass: Fix leaks upon ff_ass_add_rect() error Do this by actually incrementing the counter for the number of rects at the right time. Signed-off-by: Andreas Rheinhardt --- libavcodec/ass.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/ass.c b/libavcodec/ass.c index 907e2d7b88..725e4d42ba 100644 --- a/libavcodec/ass.c +++ b/libavcodec/ass.c @@ -118,22 +118,22 @@ int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker) { + AVSubtitleRect **rects, *rect; char *ass_str; - AVSubtitleRect **rects; rects = av_realloc_array(sub->rects, sub->num_rects+1, sizeof(*sub->rects)); if (!rects) return AVERROR(ENOMEM); sub->rects = rects; - rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); - if (!rects[sub->num_rects]) + rect = av_mallocz(sizeof(*rect)); + if (!rect) return AVERROR(ENOMEM); - rects[sub->num_rects]->type = SUBTITLE_ASS; + rects[sub->num_rects++] = rect; + rect->type = SUBTITLE_ASS; ass_str = ff_ass_get_dialog(readorder, layer, style, speaker, dialog); if (!ass_str) return AVERROR(ENOMEM); - rects[sub->num_rects]->ass = ass_str; - sub->num_rects++; + rect->ass = ass_str; return 0; } From 077167fab9067c606c374e0fd26930f78465387b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 22:44:13 +0100 Subject: [PATCH 492/894] avcodec/xsubdec: Cleanup generically upon allocation error This is possible by incrementing the counter of allocated rects directly after said allocation succeeded. Signed-off-by: Andreas Rheinhardt --- libavcodec/xsubdec.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c index 979399bae6..b483699d0a 100644 --- a/libavcodec/xsubdec.c +++ b/libavcodec/xsubdec.c @@ -101,10 +101,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, return AVERROR(ENOMEM); sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); - if (!sub->rects[0]) { - av_freep(&sub->rects); + if (!sub->rects[0]) return AVERROR(ENOMEM); - } + sub->num_rects = 1; sub->rects[0]->x = x; sub->rects[0]->y = y; sub->rects[0]->w = w; sub->rects[0]->h = h; sub->rects[0]->type = SUBTITLE_BITMAP; @@ -112,14 +111,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, sub->rects[0]->data[0] = av_malloc(w * h); sub->rects[0]->nb_colors = 4; sub->rects[0]->data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[0]->data[0] || !sub->rects[0]->data[1]) { - av_freep(&sub->rects[0]->data[1]); - av_freep(&sub->rects[0]->data[0]); - av_freep(&sub->rects[0]); - av_freep(&sub->rects); + if (!sub->rects[0]->data[0] || !sub->rects[0]->data[1]) return AVERROR(ENOMEM); - } - sub->num_rects = 1; // read palette for (i = 0; i < sub->rects[0]->nb_colors; i++) From 6e02ca35e574c344ccdb3be9fd8817af50efabd1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 22:54:45 +0100 Subject: [PATCH 493/894] avcodec/xsubdec: Use dedicated pointer for AVSubtitleRect Improves readability and slightly reduces codesize. Signed-off-by: Andreas Rheinhardt --- libavcodec/xsubdec.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c index b483699d0a..85cd7d1c20 100644 --- a/libavcodec/xsubdec.c +++ b/libavcodec/xsubdec.c @@ -52,6 +52,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AVSubtitle *sub = data; + AVSubtitleRect *rect; const uint8_t *buf_end = buf + buf_size; uint8_t *bitmap; int w, h, x, y, i, ret; @@ -100,40 +101,40 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, if (!sub->rects) return AVERROR(ENOMEM); - sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); + sub->rects[0] = rect = av_mallocz(sizeof(*sub->rects[0])); if (!sub->rects[0]) return AVERROR(ENOMEM); sub->num_rects = 1; - sub->rects[0]->x = x; sub->rects[0]->y = y; - sub->rects[0]->w = w; sub->rects[0]->h = h; - sub->rects[0]->type = SUBTITLE_BITMAP; - sub->rects[0]->linesize[0] = w; - sub->rects[0]->data[0] = av_malloc(w * h); - sub->rects[0]->nb_colors = 4; - sub->rects[0]->data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[0]->data[0] || !sub->rects[0]->data[1]) + rect->x = x; rect->y = y; + rect->w = w; rect->h = h; + rect->type = SUBTITLE_BITMAP; + rect->linesize[0] = w; + rect->data[0] = av_malloc(w * h); + rect->nb_colors = 4; + rect->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!rect->data[0] || !rect->data[1]) return AVERROR(ENOMEM); // read palette - for (i = 0; i < sub->rects[0]->nb_colors; i++) - ((uint32_t*)sub->rects[0]->data[1])[i] = bytestream_get_be24(&buf); + for (i = 0; i < rect->nb_colors; i++) + ((uint32_t*)rect->data[1])[i] = bytestream_get_be24(&buf); if (!has_alpha) { // make all except background (first entry) non-transparent - for (i = 1; i < sub->rects[0]->nb_colors; i++) - ((uint32_t *)sub->rects[0]->data[1])[i] |= 0xff000000; + for (i = 1; i < rect->nb_colors; i++) + ((uint32_t *)rect->data[1])[i] |= 0xff000000; } else { - for (i = 0; i < sub->rects[0]->nb_colors; i++) - ((uint32_t *)sub->rects[0]->data[1])[i] |= (unsigned)*buf++ << 24; + for (i = 0; i < rect->nb_colors; i++) + ((uint32_t *)rect->data[1])[i] |= (unsigned)*buf++ << 24; } // process RLE-compressed data if ((ret = init_get_bits8(&gb, buf, buf_end - buf)) < 0) return ret; - bitmap = sub->rects[0]->data[0]; + bitmap = rect->data[0]; for (y = 0; y < h; y++) { // interlaced: do odd lines - if (y == (h + 1) / 2) bitmap = sub->rects[0]->data[0] + w; + if (y == (h + 1) / 2) bitmap = rect->data[0] + w; for (x = 0; x < w; ) { int log2 = ff_log2_tab[show_bits(&gb, 8)]; int run = get_bits(&gb, 14 - 4 * (log2 >> 1)); From 8ff3fbf6bca0ee897e458fc27e5f967cdcbc16c7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 10 Dec 2021 23:20:57 +0100 Subject: [PATCH 494/894] avcodec/decode: Reset *got_sub_ptr on error Signed-off-by: Andreas Rheinhardt --- libavcodec/decode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index afe2c0c3c1..0912f86a14 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -862,8 +862,8 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, "Invalid UTF-8 in decoded subtitles text; " "maybe missing -sub_charenc option\n"); avsubtitle_free(sub); - ret = AVERROR_INVALIDDATA; - break; + *got_sub_ptr = 0; + return AVERROR_INVALIDDATA; } } From 7a5f7caee9ebd58a025bd804e89f33de9f217b2a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 15:10:10 +0100 Subject: [PATCH 495/894] avcodec/speedhq: Replace always-true check by assert Should fix Coverity tickets #1473572 and #1473504. Signed-off-by: Andreas Rheinhardt --- libavcodec/speedhq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/speedhq.c b/libavcodec/speedhq.c index 91ba80ebd3..743dacc6ce 100644 --- a/libavcodec/speedhq.c +++ b/libavcodec/speedhq.c @@ -295,7 +295,8 @@ static int decode_speedhq_border(const SHQContext *s, GetBitContext *gb, AVFrame if (s->subsampling == SHQ_SUBSAMPLING_420) { dest_cb = frame->data[1] + frame->linesize[1] * (y/2 + field_number) + x / 2; dest_cr = frame->data[2] + frame->linesize[2] * (y/2 + field_number) + x / 2; - } else if (s->subsampling == SHQ_SUBSAMPLING_422) { + } else { + av_assert2(s->subsampling == SHQ_SUBSAMPLING_422); dest_cb = frame->data[1] + frame->linesize[1] * (y + field_number) + x / 2; dest_cr = frame->data[2] + frame->linesize[2] * (y + field_number) + x / 2; } From 0a25abdacd8a4dd4836cf1584ccab47204813ed2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 15:32:14 +0100 Subject: [PATCH 496/894] avformat/moflex: Free AVPackets via av_packet_free() on error (This is not a leak as long as av_free() completely frees blank packets.) Signed-off-by: Andreas Rheinhardt --- libavformat/moflex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/moflex.c b/libavformat/moflex.c index 234b0fb06e..67adebe5e0 100644 --- a/libavformat/moflex.c +++ b/libavformat/moflex.c @@ -383,4 +383,5 @@ const AVInputFormat ff_moflex_demuxer = { .read_close = moflex_read_close, .extensions = "moflex", .flags = AVFMT_GENERIC_INDEX, + .flags_internal = FF_FMT_INIT_CLEANUP, }; From 38e5ca9310b1a4dbb72fbe28769c9119bb880691 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 16:02:22 +0100 Subject: [PATCH 497/894] avformat/moflex: Don't use uninitialized timebase for data stream Signed-off-by: Andreas Rheinhardt --- libavformat/moflex.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavformat/moflex.c b/libavformat/moflex.c index 67adebe5e0..1d342417f7 100644 --- a/libavformat/moflex.c +++ b/libavformat/moflex.c @@ -172,7 +172,7 @@ static int moflex_read_sync(AVFormatContext *s) unsigned type, ssize, codec_id = 0; unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0; int stream_index = -1; - AVRational fps; + AVRational tb = av_make_q(0, 1); read_var_byte(s, &type); read_var_byte(s, &ssize); @@ -195,6 +195,7 @@ static int moflex_read_sync(AVFormatContext *s) return AVERROR_PATCHWELCOME; } sample_rate = avio_rb24(pb) + 1; + tb = av_make_q(1, sample_rate); channels = avio_r8(pb) + 1; break; case 1: @@ -208,8 +209,8 @@ static int moflex_read_sync(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Unsupported video codec: %d\n", codec_id); return AVERROR_PATCHWELCOME; } - fps.num = avio_rb16(pb); - fps.den = avio_rb16(pb); + tb.den = avio_rb16(pb); + tb.num = avio_rb16(pb); width = avio_rb16(pb); height = avio_rb16(pb); avio_skip(pb, type == 3 ? 3 : 2); @@ -237,10 +238,8 @@ static int moflex_read_sync(AVFormatContext *s) if (!st->priv_data) return AVERROR(ENOMEM); - if (sample_rate) - avpriv_set_pts_info(st, 63, 1, sample_rate); - else - avpriv_set_pts_info(st, 63, fps.den, fps.num); + if (tb.num) + avpriv_set_pts_info(st, 63, tb.num, tb.den); } } From 3f46ffe956a563a975b65fcb0bcf131fd30956ff Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Wed, 1 Dec 2021 11:19:47 +0800 Subject: [PATCH 498/894] avformat/aviobuf: fix double free by return early on error Because the s->buffer has been freed by av_freep in avio_closep. It should not av_freep the buffer in label fail after avio_closep. Then just move the av_freep before avio_closep and remove the label fail. Reported-by: TOTE Robot Reviewed-by: Zhao Zhili Signed-off-by: Steven Liu --- libavformat/aviobuf.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 969c127b23..14d4b8f240 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -977,18 +977,19 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) (int (*)(void *, uint8_t *, int)) ffurl_read, (int (*)(void *, uint8_t *, int)) ffurl_write, (int64_t (*)(void *, int64_t, int))ffurl_seek); - if (!*s) - goto fail; - + if (!*s) { + av_freep(&buffer); + return AVERROR(ENOMEM); + } (*s)->protocol_whitelist = av_strdup(h->protocol_whitelist); if (!(*s)->protocol_whitelist && h->protocol_whitelist) { avio_closep(s); - goto fail; + return AVERROR(ENOMEM); } (*s)->protocol_blacklist = av_strdup(h->protocol_blacklist); if (!(*s)->protocol_blacklist && h->protocol_blacklist) { avio_closep(s); - goto fail; + return AVERROR(ENOMEM); } (*s)->direct = h->flags & AVIO_FLAG_DIRECT; @@ -1006,9 +1007,6 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) ((FFIOContext*)(*s))->short_seek_get = (int (*)(void *))ffurl_get_short_seek; (*s)->av_class = &ff_avio_class; return 0; -fail: - av_freep(&buffer); - return AVERROR(ENOMEM); } URLContext* ffio_geturlcontext(AVIOContext *s) From a4580bf95985e033eb8857156db3670eeec48131 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 15 Dec 2021 10:47:28 +0800 Subject: [PATCH 499/894] fftools/cmdutils: Avoid crash when opts could not be allocated If 'opts' could not be allocated, exiting the program to avoid crash when release it. Reported-by: TOTE Robot Signed-off-by: Yu Yang Signed-off-by: Andreas Rheinhardt --- fftools/cmdutils.c | 2 +- fftools/cmdutils.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 3c8e5a82cd..882584e9c2 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2187,7 +2187,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, if (!opts) { av_log(NULL, AV_LOG_ERROR, "Could not alloc memory for stream options.\n"); - return NULL; + exit_program(1); } for (i = 0; i < s->nb_streams; i++) opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 82cda208be..50eed9b13a 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -430,8 +430,8 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, * Each dictionary will contain the options from codec_opts which can * be applied to the corresponding stream codec context. * - * @return pointer to the created array of dictionaries, NULL if it - * cannot be created + * @return pointer to the created array of dictionaries. + * Calls exit() on failure. */ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts); From 0ab5d7e92b7970616066b634354d2233927ee36b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 15 Dec 2021 16:49:13 +0100 Subject: [PATCH 500/894] avcodec/tests: Update .gitignore file Forgotten in 136865413c04760aeeda6079002bc3c1f9ae230a. Signed-off-by: Andreas Rheinhardt --- libavcodec/tests/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore index 69bf891f44..2acfc4e804 100644 --- a/libavcodec/tests/.gitignore +++ b/libavcodec/tests/.gitignore @@ -1,3 +1,4 @@ +/avcodec /avfft /avpacket /cabac @@ -18,4 +19,3 @@ /mpeg12framerate /rangecoder /snowenc -/utils From 76a3f961f8e004da3ebc32640baf5c5ea4406a3b Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 16 Dec 2021 09:41:56 -0300 Subject: [PATCH 501/894] x86/scale_avx2: add missing check for AVX2 assembler support Should fix compilation with old yasm. Signed-off-by: James Almer --- libswscale/x86/scale_avx2.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libswscale/x86/scale_avx2.asm b/libswscale/x86/scale_avx2.asm index 4e4fe5d794..2cd7e968d3 100644 --- a/libswscale/x86/scale_avx2.asm +++ b/libswscale/x86/scale_avx2.asm @@ -106,7 +106,9 @@ REP_RET %endmacro %if ARCH_X86_64 +%if HAVE_AVX2_EXTERNAL INIT_YMM avx2 SCALE_FUNC 4 SCALE_FUNC X4 %endif +%endif From 86663963e6419a127cf52a03758855f4f8f8689f Mon Sep 17 00:00:00 2001 From: Alan Kelly Date: Thu, 16 Dec 2021 17:05:48 +0100 Subject: [PATCH 502/894] x86/swscale: fix minor coding style issues Signed-off-by: James Almer --- libswscale/x86/swscale.c | 14 +++++++------- tests/checkasm/sw_scale.c | 3 +-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index 164b06d6ba..c49a05c37b 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -578,13 +578,13 @@ switch(c->dstBpc){ \ break; \ } - if (EXTERNAL_AVX2_FAST(cpu_flags)){ - if ((c->srcBpc == 8) && (c->dstBpc <= 14)){ - if(c->chrDstW % 16 == 0) - ASSIGN_AVX2_SCALE_FUNC(c->hcScale, c->hChrFilterSize); - if(c->dstW % 16 == 0) - ASSIGN_AVX2_SCALE_FUNC(c->hyScale, c->hLumFilterSize); - } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + if ((c->srcBpc == 8) && (c->dstBpc <= 14)) { + if (c->chrDstW % 16 == 0) + ASSIGN_AVX2_SCALE_FUNC(c->hcScale, c->hChrFilterSize); + if (c->dstW % 16 == 0) + ASSIGN_AVX2_SCALE_FUNC(c->hyScale, c->hLumFilterSize); + } } if (EXTERNAL_AVX2_FAST(cpu_flags)) { diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index 011cb46428..f4912e6c2c 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -217,9 +217,8 @@ static void check_hscale(void) } ff_sws_init_scale(ctx); memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); - if (cpu_flags & AV_CPU_FLAG_AVX2){ + if (cpu_flags & AV_CPU_FLAG_AVX2) ff_shuffle_filter_coefficients(ctx, filterPosAvx, width, filterAvx2, SRC_PIXELS); - } if (check_func(ctx->hcScale, "hscale_%d_to_%d_width%d", ctx->srcBpc, ctx->dstBpc + 1, width)) { memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0])); From 9092e58c4469f5488f305fdb85e34e61bba7b04a Mon Sep 17 00:00:00 2001 From: Alan Kelly Date: Thu, 16 Dec 2021 17:27:10 +0100 Subject: [PATCH 503/894] x86/scale_avx2: Change asm indent from 2 to 4 spaces. Signed-off-by: James Almer --- libswscale/x86/scale_avx2.asm | 96 +++++++++++++++++------------------ 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/libswscale/x86/scale_avx2.asm b/libswscale/x86/scale_avx2.asm index 2cd7e968d3..eb472db12f 100644 --- a/libswscale/x86/scale_avx2.asm +++ b/libswscale/x86/scale_avx2.asm @@ -45,63 +45,63 @@ SECTION .text %macro SCALE_FUNC 1 cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, count, inner - pxor m0, m0 - mova m15, [swizzle] - mov countq, $0 - movsxd wq, wd + pxor m0, m0 + mova m15, [swizzle] + mov countq, $0 + movsxd wq, wd %ifidn %1, X4 - mova m14, [four] - shr fltsized, 2 + mova m14, [four] + shr fltsized, 2 %endif .loop: - movu m1, [fltposq] - movu m2, [fltposq+32] + movu m1, [fltposq] + movu m2, [fltposq+32] %ifidn %1, X4 - pxor m9, m9 - pxor m10, m10 - pxor m11, m11 - pxor m12, m12 - mov innerq, $0 + pxor m9, m9 + pxor m10, m10 + pxor m11, m11 + pxor m12, m12 + mov innerq, $0 .innerloop: %endif - vpcmpeqd m13, m13 - vpgatherdd m3,[srcmemq + m1], m13 - vpcmpeqd m13, m13 - vpgatherdd m4,[srcmemq + m2], m13 - vpunpcklbw m5, m3, m0 - vpunpckhbw m6, m3, m0 - vpunpcklbw m7, m4, m0 - vpunpckhbw m8, m4, m0 - vpmaddwd m5, m5, [filterq] - vpmaddwd m6, m6, [filterq + 32] - vpmaddwd m7, m7, [filterq + 64] - vpmaddwd m8, m8, [filterq + 96] - add filterq, $80 + vpcmpeqd m13, m13 + vpgatherdd m3,[srcmemq + m1], m13 + vpcmpeqd m13, m13 + vpgatherdd m4,[srcmemq + m2], m13 + vpunpcklbw m5, m3, m0 + vpunpckhbw m6, m3, m0 + vpunpcklbw m7, m4, m0 + vpunpckhbw m8, m4, m0 + vpmaddwd m5, m5, [filterq] + vpmaddwd m6, m6, [filterq + 32] + vpmaddwd m7, m7, [filterq + 64] + vpmaddwd m8, m8, [filterq + 96] + add filterq, $80 %ifidn %1, X4 - paddd m9, m5 - paddd m10, m6 - paddd m11, m7 - paddd m12, m8 - paddd m1, m14 - paddd m2, m14 - add innerq, $1 - cmp innerq, fltsizeq - jl .innerloop - vphaddd m5, m9, m10 - vphaddd m6, m11, m12 + paddd m9, m5 + paddd m10, m6 + paddd m11, m7 + paddd m12, m8 + paddd m1, m14 + paddd m2, m14 + add innerq, $1 + cmp innerq, fltsizeq + jl .innerloop + vphaddd m5, m9, m10 + vphaddd m6, m11, m12 %else - vphaddd m5, m5, m6 - vphaddd m6, m7, m8 + vphaddd m5, m5, m6 + vphaddd m6, m7, m8 %endif - vpsrad m5, 7 - vpsrad m6, 7 - vpackssdw m5, m5, m6 - vpermd m5, m15, m5 - vmovdqu [dstq + countq * 2], m5 - add fltposq, $40 - add countq, $10 - cmp countq, wq - jl .loop + vpsrad m5, 7 + vpsrad m6, 7 + vpackssdw m5, m5, m6 + vpermd m5, m15, m5 + vmovdqu [dstq + countq * 2], m5 + add fltposq, $40 + add countq, $10 + cmp countq, wq + jl .loop REP_RET %endmacro From 99b2700f5bf887cf95316a2f9e8c1082b11982ba Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Dec 2021 18:37:13 +0100 Subject: [PATCH 504/894] avformat/mvdec: Use 64 bit in timestamp computation Fixes: division by zero Fixes: 42198/clusterfuzz-testcase-minimized-ffmpeg_dem_MV_fuzzer-5054366405492736.fuzz Fixes: 42222/clusterfuzz-testcase-minimized-ffmpeg_dem_MV_fuzzer-4561249331970048 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Peter Ross Signed-off-by: Michael Niedermayer --- libavformat/mvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 8b54a9ab04..5d184f20a4 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -381,7 +381,7 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 8); av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codecpar->channels * bytes_per_sample); + timestamp += asize / (ast->codecpar->channels * (uint64_t)bytes_per_sample); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); From db3fd5ab3190ca4298d29b12153859a51f9a02fd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Dec 2021 18:37:12 +0100 Subject: [PATCH 505/894] tools/target_dec_fuzzer: Adjust threshold for prores Fixes: Timeout Fixes: 42072/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PRORES_fuzzer-4957999452520448 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 0c59242e3e..13766d22b9 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -193,6 +193,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_APNG: maxpixels /= 128; break; case AV_CODEC_ID_QTRLE: maxpixels /= 16; break; case AV_CODEC_ID_PAF_VIDEO: maxpixels /= 16; break; + case AV_CODEC_ID_PRORES: maxpixels /= 256; break; case AV_CODEC_ID_RASC: maxpixels /= 16; break; case AV_CODEC_ID_SANM: maxpixels /= 16; break; case AV_CODEC_ID_SCPR: maxpixels /= 32; break; From eab91c3e2e94cf4934ec9da50be6fea3c73e8f36 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 16 Dec 2021 17:16:17 -0300 Subject: [PATCH 506/894] x86/scale_avx2: don't use $ for hex literals Fixes compilation with AVX2 enabled yasm. Signed-off-by: James Almer --- libswscale/x86/scale_avx2.asm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libswscale/x86/scale_avx2.asm b/libswscale/x86/scale_avx2.asm index eb472db12f..20acdbd633 100644 --- a/libswscale/x86/scale_avx2.asm +++ b/libswscale/x86/scale_avx2.asm @@ -47,7 +47,7 @@ SECTION .text cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, count, inner pxor m0, m0 mova m15, [swizzle] - mov countq, $0 + xor countq, countq movsxd wq, wd %ifidn %1, X4 mova m14, [four] @@ -61,7 +61,7 @@ cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, pxor m10, m10 pxor m11, m11 pxor m12, m12 - mov innerq, $0 + xor innerq, innerq .innerloop: %endif vpcmpeqd m13, m13 @@ -76,7 +76,7 @@ cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, vpmaddwd m6, m6, [filterq + 32] vpmaddwd m7, m7, [filterq + 64] vpmaddwd m8, m8, [filterq + 96] - add filterq, $80 + add filterq, 0x80 %ifidn %1, X4 paddd m9, m5 paddd m10, m6 @@ -84,7 +84,7 @@ cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, paddd m12, m8 paddd m1, m14 paddd m2, m14 - add innerq, $1 + add innerq, 1 cmp innerq, fltsizeq jl .innerloop vphaddd m5, m9, m10 @@ -98,8 +98,8 @@ cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, vpackssdw m5, m5, m6 vpermd m5, m15, m5 vmovdqu [dstq + countq * 2], m5 - add fltposq, $40 - add countq, $10 + add fltposq, 0x40 + add countq, 0x10 cmp countq, wq jl .loop REP_RET From 7b24615565fd488e7e3a435102979a5ea85fe2fe Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Dec 2021 18:40:03 +0100 Subject: [PATCH 507/894] avformat/vivo: Do not use the general expression evaluator for parsing a floating point value Fixes: Timeout Fixes: 41564/clusterfuzz-testcase-minimized-ffmpeg_dem_VIVO_fuzzer-6309014024093696 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/vivo.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavformat/vivo.c b/libavformat/vivo.c index b2904cd25a..6447ec7ee8 100644 --- a/libavformat/vivo.c +++ b/libavformat/vivo.c @@ -26,6 +26,7 @@ * @sa http://wiki.multimedia.cx/index.php?title=Vivo */ +#include "libavutil/avstring.h" #include "libavutil/parseutils.h" #include "avformat.h" #include "internal.h" @@ -206,11 +207,12 @@ static int vivo_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; value_used = 1; } else if (!strcmp(key, "FPS")) { - AVRational tmp; + double d; + if (av_sscanf(value, "%f", &d) != 1) + return AVERROR_INVALIDDATA; value_used = 1; - if (!av_parse_ratio(&tmp, value, 10000, AV_LOG_WARNING, s)) - fps = av_inv_q(tmp); + fps = av_inv_q(av_d2q(d, 10000)); } if (!value_used) From bf1e93bdc9aaa4fd5c231030b5368aae0df018ee Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 6 Dec 2021 11:38:39 +0100 Subject: [PATCH 508/894] avformat/vivo: Favor setting fps from explicit fractions Signed-off-by: Michael Niedermayer --- libavformat/vivo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/vivo.c b/libavformat/vivo.c index 6447ec7ee8..2a08e1df03 100644 --- a/libavformat/vivo.c +++ b/libavformat/vivo.c @@ -121,7 +121,7 @@ static int vivo_get_packet_header(AVFormatContext *s) static int vivo_read_header(AVFormatContext *s) { VivoContext *vivo = s->priv_data; - AVRational fps = { 1, 25}; + AVRational fps = { 0 }; AVStream *ast, *vst; unsigned char *line, *line_end, *key, *value; long value_int; @@ -212,13 +212,16 @@ static int vivo_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; value_used = 1; - fps = av_inv_q(av_d2q(d, 10000)); + if (!fps.num && !fps.den) + fps = av_inv_q(av_d2q(d, 10000)); } if (!value_used) av_dict_set(&s->metadata, key, value, 0); } } + if (!fps.num || !fps.den) + fps = (AVRational){ 1, 25 }; avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); avpriv_set_pts_info(vst, 64, fps.num, fps.den); From 562021e2fd4d74589905d9c566c686394d2b0526 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Dec 2021 20:48:54 +0100 Subject: [PATCH 509/894] avformat/mov: Check next offset in mov_read_dref() Fixes: signed integer overflow: 9223372036200463215 + 1109914409 cannot be represented in type 'long' Fixes: 41480/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-6553086177443840 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 9ebfa0bcc7..2aed6e80ef 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -610,11 +610,13 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < entries; i++) { MOVDref *dref = &sc->drefs[i]; uint32_t size = avio_rb32(pb); - int64_t next = avio_tell(pb) + size - 4; + int64_t next = avio_tell(pb); - if (size < 12) + if (size < 12 || next < 0 || next > INT64_MAX - size) return AVERROR_INVALIDDATA; + next += size - 4; + dref->type = avio_rl32(pb); avio_rb32(pb); // version + flags From 8e96410e1b8360b6544b74836f3d6971e8ab2fc1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 30 Nov 2021 20:03:22 +0100 Subject: [PATCH 510/894] avcodec/speexdec: Avoid violating the vector_fmul_scalar() API Fixes: out of array access Fixes: 40054/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SPEEX_fuzzer-6713285764841472 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/speexdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c index e263d4c48c..1c33607db2 100644 --- a/libavcodec/speexdec.c +++ b/libavcodec/speexdec.c @@ -1545,7 +1545,7 @@ static int speex_decode_frame(AVCodecContext *avctx, void *data, if ((ret = init_get_bits8(&s->gb, avpkt->data, buf_size)) < 0) return ret; - frame->nb_samples = s->frame_size * s->frames_per_packet; + frame->nb_samples = FFALIGN(s->frame_size * s->frames_per_packet, 4); if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -1560,6 +1560,7 @@ static int speex_decode_frame(AVCodecContext *avctx, void *data, dst = (float *)frame->extended_data[0]; s->fdsp->vector_fmul_scalar(dst, dst, scale, frame->nb_samples * frame->channels); + frame->nb_samples = s->frame_size * s->frames_per_packet; *got_frame_ptr = 1; From e22ec484aab7a75d5cefb654885c18c3a7b8e948 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 27 Nov 2021 20:48:27 +0100 Subject: [PATCH 511/894] avformat/cinedec: Avoid repeatedly allocating packets beyond the input Fixes: Timeout Fixes: 41025/clusterfuzz-testcase-minimized-ffmpeg_dem_CINE_fuzzer-5540848285122560 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/cinedec.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libavformat/cinedec.c b/libavformat/cinedec.c index c83a4c1471..f4779b2676 100644 --- a/libavformat/cinedec.c +++ b/libavformat/cinedec.c @@ -33,6 +33,7 @@ typedef struct { uint64_t pts; + uint64_t maxsize; } CineDemuxContext; /** Compression */ @@ -288,21 +289,32 @@ static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt) FFStream *const sti = ffstream(st); AVIOContext *pb = avctx->pb; int n, size, ret; + int64_t ret64; if (cine->pts >= sti->nb_index_entries) return AVERROR_EOF; - avio_seek(pb, sti->index_entries[cine->pts].pos, SEEK_SET); + ret64 = avio_seek(pb, sti->index_entries[cine->pts].pos, SEEK_SET); + if (ret64 < 0) + return ret64; n = avio_rl32(pb); if (n < 8) return AVERROR_INVALIDDATA; avio_skip(pb, n - 8); size = avio_rl32(pb); + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + + if (cine->maxsize && sti->index_entries[cine->pts].pos + size + n > cine->maxsize) + size = cine->maxsize - sti->index_entries[cine->pts].pos - n; ret = av_get_packet(pb, pkt, size); if (ret < 0) return ret; + if (ret != size) + cine->maxsize = sti->index_entries[cine->pts].pos + n + ret; + pkt->pts = cine->pts++; pkt->stream_index = 0; pkt->flags |= AV_PKT_FLAG_KEY; From 0dcd95ef8a2e16ed930296567ab1044e33602a34 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 7 Dec 2021 09:14:08 +0100 Subject: [PATCH 512/894] avformat/4xm: Consider max_streams on reallocating tracks array Fixes: OOM Fixes: 41595/clusterfuzz-testcase-minimized-ffmpeg_dem_FOURXM_fuzzer-6355979363549184 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/4xm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/4xm.c b/libavformat/4xm.c index f918b1fc57..848991af5b 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -137,7 +137,8 @@ static int parse_strk(AVFormatContext *s, return AVERROR_INVALIDDATA; track = AV_RL32(buf + 8); - if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) { + if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1 || + track >= s->max_streams) { av_log(s, AV_LOG_ERROR, "current_track too large\n"); return AVERROR_INVALIDDATA; } From dd949124793c722ed55dead9da245574ace81968 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 7 Dec 2021 09:14:09 +0100 Subject: [PATCH 513/894] avformat/4xm: Check for duplicate track ids Signed-off-by: Michael Niedermayer --- libavformat/4xm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/4xm.c b/libavformat/4xm.c index 848991af5b..e307560014 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -149,6 +149,9 @@ static int parse_strk(AVFormatContext *s, memset(&fourxm->tracks[fourxm->track_count], 0, sizeof(AudioTrack) * (track + 1 - fourxm->track_count)); fourxm->track_count = track + 1; + } else { + if (fourxm->tracks[track].bits) + return AVERROR_INVALIDDATA; } fourxm->tracks[track].adpcm = AV_RL32(buf + 12); fourxm->tracks[track].channels = AV_RL32(buf + 36); From 81c6b8ffe87bf01c4ba7d22773b0aeda4376d37c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 20:36:05 +0100 Subject: [PATCH 514/894] avcodec/mpegvideo: Move closed_gop to Mpeg1Context Only used there and only by the main thread. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12dec.c | 8 +++++--- libavcodec/mpegvideo.c | 1 - libavcodec/mpegvideo.h | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 09b2902bca..672031b6db 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -69,6 +69,7 @@ typedef struct Mpeg1Context { int rc_buffer_size; AVRational frame_rate_ext; /* MPEG-2 specific framerate modificator */ int sync; /* Did we reach a sync point like a GOP/SEQ/KEYFrame? */ + int closed_gop; int tmpgexs; int first_slice; int extradata_decoded; @@ -2449,7 +2450,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, tc = s-> timecode_frame_start = get_bits(&s->gb, 25); - s->closed_gop = get_bits1(&s->gb); + s1->closed_gop = get_bits1(&s->gb); /* broken_link indicates that after editing the * reference frames of the first B-Frames after GOP I-Frame * are missing (open gop) */ @@ -2460,7 +2461,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, av_timecode_make_mpeg_tc_string(tcbuf, tc); av_log(s->avctx, AV_LOG_DEBUG, "GOP (%s) closed_gop=%d broken_link=%d\n", - tcbuf, s->closed_gop, broken_link); + tcbuf, s1->closed_gop, broken_link); } } @@ -2694,7 +2695,7 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, /* Skip B-frames if we do not have reference frames and * GOP is not closed. */ if (s2->pict_type == AV_PICTURE_TYPE_B) { - if (!s2->closed_gop) { + if (!s->closed_gop) { skip_frame = 1; av_log(s2->avctx, AV_LOG_DEBUG, "Skipping B slice due to open GOP\n"); @@ -2882,6 +2883,7 @@ static void flush(AVCodecContext *avctx) Mpeg1Context *s = avctx->priv_data; s->sync = 0; + s->closed_gop = 0; ff_mpeg_flush(avctx); } diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index ba5b51955e..55399a7478 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2317,7 +2317,6 @@ void ff_mpeg_flush(AVCodecContext *avctx){ ff_mpeg_unref_picture(s->avctx, &s->next_picture); s->mb_x= s->mb_y= 0; - s->closed_gop= 0; #if FF_API_FLAG_TRUNCATED s->parse_context.state= -1; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index e90669b776..85f02b1355 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -198,7 +198,6 @@ typedef struct MpegEncContext { int *lambda_table; int adaptive_quant; ///< use adaptive quantization int dquant; ///< qscale difference to prev qscale - int closed_gop; ///< MPEG1/2 GOP is closed int pict_type; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... int vbv_delay; int last_pict_type; //FIXME removes From 0abdf63ae7fc9c194bc1df612c649eb7d110b9cc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 20:42:46 +0100 Subject: [PATCH 515/894] avcodec/mpegvideo: Don't update encoder-only fields for decoders ff_mpeg_update_thread_context() is only used by decoders. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 55399a7478..b5ff4cec69 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -658,12 +658,6 @@ do {\ memcpy(&s->progressive_sequence, &s1->progressive_sequence, (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); - if (!s1->first_field) { - s->last_pict_type = s1->pict_type; - if (s1->current_picture_ptr) - s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f->quality; - } - return 0; } From b72723d415ff059aaf1038fa98900eb3e93896d3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 21:32:21 +0100 Subject: [PATCH 516/894] avcodec/mpegvideo_enc, vc1dec: Remove always-false check Mpeg1EncContext.droppable is only nonzero for the FLV decoder. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 3 +-- libavcodec/vc1dec.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index f804b8215d..d33cf9477d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1658,8 +1658,7 @@ static int frame_start(MpegEncContext *s) if (s->pict_type != AV_PICTURE_TYPE_B) { s->last_picture_ptr = s->next_picture_ptr; - if (!s->droppable) - s->next_picture_ptr = s->current_picture_ptr; + s->next_picture_ptr = s->current_picture_ptr; } if (s->last_picture_ptr) { diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index e636fa6160..267d72d15b 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -862,7 +862,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; /* skip B-frames if we don't have reference frames */ - if (!s->last_picture_ptr && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) { + if (!s->last_picture_ptr && s->pict_type == AV_PICTURE_TYPE_B) { av_log(v->s.avctx, AV_LOG_DEBUG, "Skipping B frame without reference frames\n"); goto end; } From 2ac3e32802c6b9553677d472fe96a8c3ba237662 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Dec 2021 23:50:11 +0100 Subject: [PATCH 517/894] avcodec/mpegvideo: Don't allocate encoder-only buffers when decoding Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index b5ff4cec69..e2cdba8bb1 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -768,11 +768,9 @@ static int init_context_frame(MpegEncContext *s) !FF_ALLOC_TYPED_ARRAY (s->cplx_tab, mb_array_size) || !FF_ALLOC_TYPED_ARRAY (s->bits_tab, mb_array_size)) return AVERROR(ENOMEM); - } if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { - /* interlaced direct mode decoding tables */ for (i = 0; i < 2; i++) { int j, k; for (j = 0; j < 2; j++) { @@ -782,15 +780,27 @@ static int init_context_frame(MpegEncContext *s) s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1; } - if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2) || - !FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) + if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2)) return AVERROR(ENOMEM); - s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; } if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_select_table[i], mv_table_size * 2)) return AVERROR(ENOMEM); } } + } + + if (s->codec_id == AV_CODEC_ID_MPEG4 || + (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + /* interlaced direct mode decoding tables */ + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) + return AVERROR(ENOMEM); + s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; + } + } + } + if (s->out_format == FMT_H263) { /* cbp values, cbp, ac_pred, pred_dir */ if (!FF_ALLOCZ_TYPED_ARRAY(s->coded_block_base, y_size + (s->mb_height&1)*2*s->b8_stride) || From 9088cc6df9de86d69c531b4f7b4da2b8b4b5299d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 01:22:04 +0100 Subject: [PATCH 518/894] avcodec/mpegvideo: Allocate several buffers jointly Reduces the amount of allocations and frees. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 46 ++++++++++++++++++++++++++---------------- libavcodec/mpegvideo.h | 8 ++++---- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index e2cdba8bb1..be47ccb8ed 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -769,34 +769,44 @@ static int init_context_frame(MpegEncContext *s) !FF_ALLOC_TYPED_ARRAY (s->bits_tab, mb_array_size)) return AVERROR(ENOMEM); +#define ALLOCZ_ARRAYS(p, mult, numb) ((p) = av_calloc(numb, mult * sizeof(*(p)))) if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + int16_t (*tmp1)[2]; + uint8_t *tmp2; + if (!(tmp1 = ALLOCZ_ARRAYS(s->b_field_mv_table_base, 8, mv_table_size)) || + !(tmp2 = ALLOCZ_ARRAYS(s->b_field_select_table[0][0], 2 * 4, mv_table_size)) || + !ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * 2, mv_table_size)) + return AVERROR(ENOMEM); + + s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; + tmp1 += s->mb_stride + 1; + for (i = 0; i < 2; i++) { int j, k; for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { - if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_mv_table_base[i][j][k], mv_table_size)) - return AVERROR(ENOMEM); - s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + - s->mb_stride + 1; + s->b_field_mv_table[i][j][k] = tmp1; + tmp1 += mv_table_size; } - if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2)) - return AVERROR(ENOMEM); + s->b_field_select_table[i][j] = tmp2; + tmp2 += 2 * mv_table_size; } - if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_select_table[i], mv_table_size * 2)) - return AVERROR(ENOMEM); } } } if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + int16_t (*tmp)[2]; /* interlaced direct mode decoding tables */ + if (!(tmp = ALLOCZ_ARRAYS(s->p_field_mv_table_base, 4, mv_table_size))) + return AVERROR(ENOMEM); + tmp += s->mb_stride + 1; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { - if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) - return AVERROR(ENOMEM); - s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; + s->p_field_mv_table[i][j] = tmp; + tmp += mv_table_size; } } } @@ -880,14 +890,14 @@ static void clear_context(MpegEncContext *s) s->b_bidir_forw_mv_table = NULL; s->b_bidir_back_mv_table = NULL; s->b_direct_mv_table = NULL; + s->b_field_mv_table_base = NULL; + s->p_field_mv_table_base = NULL; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { - s->b_field_mv_table_base[i][j][k] = NULL; s->b_field_mv_table[i][j][k] = NULL; } s->b_field_select_table[i][j] = NULL; - s->p_field_mv_table_base[i][j] = NULL; s->p_field_mv_table[i][j] = NULL; } s->p_field_select_table[i] = NULL; @@ -1026,17 +1036,19 @@ static void free_context_frame(MpegEncContext *s) s->b_bidir_forw_mv_table = NULL; s->b_bidir_back_mv_table = NULL; s->b_direct_mv_table = NULL; + av_freep(&s->b_field_mv_table_base); + av_freep(&s->b_field_select_table[0][0]); + av_freep(&s->p_field_mv_table_base); + av_freep(&s->p_field_select_table[0]); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { - av_freep(&s->b_field_mv_table_base[i][j][k]); s->b_field_mv_table[i][j][k] = NULL; } - av_freep(&s->b_field_select_table[i][j]); - av_freep(&s->p_field_mv_table_base[i][j]); + s->b_field_select_table[i][j] = NULL; s->p_field_mv_table[i][j] = NULL; } - av_freep(&s->p_field_select_table[i]); + s->p_field_select_table[i] = NULL; } av_freep(&s->dc_val_base); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 85f02b1355..879b019ffc 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -232,8 +232,8 @@ typedef struct MpegEncContext { int16_t (*b_bidir_forw_mv_table_base)[2]; int16_t (*b_bidir_back_mv_table_base)[2]; int16_t (*b_direct_mv_table_base)[2]; - int16_t (*p_field_mv_table_base[2][2])[2]; - int16_t (*b_field_mv_table_base[2][2][2])[2]; + int16_t (*p_field_mv_table_base)[2]; + int16_t (*b_field_mv_table_base)[2]; int16_t (*p_mv_table)[2]; ///< MV table (1MV per MB) P-frame encoding int16_t (*b_forw_mv_table)[2]; ///< MV table (1MV per MB) forward mode B-frame encoding int16_t (*b_back_mv_table)[2]; ///< MV table (1MV per MB) backward mode B-frame encoding @@ -242,8 +242,8 @@ typedef struct MpegEncContext { int16_t (*b_direct_mv_table)[2]; ///< MV table (1MV per MB) direct mode B-frame encoding int16_t (*p_field_mv_table[2][2])[2]; ///< MV table (2MV per MB) interlaced P-frame encoding int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced B-frame encoding - uint8_t (*p_field_select_table[2]); - uint8_t (*b_field_select_table[2][2]); + uint8_t (*p_field_select_table[2]); ///< Only the first element is allocated + uint8_t (*b_field_select_table[2][2]); ///< Only the first element is allocated int motion_est; ///< ME algorithm int me_penalty_compensation; int me_pre; ///< prepass for motion estimation From f860dfe555349611ba20bb44e62487ee080c5ae1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 01:32:32 +0100 Subject: [PATCH 519/894] avcodec/h263: Remove declaration of inexistent function Forgotten in c46eeae2a80dfe0046c15b542e8b9a2c78f19bf7. Signed-off-by: Andreas Rheinhardt --- libavcodec/h263.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libavcodec/h263.h b/libavcodec/h263.h index d6bef8318d..84a3a19517 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -87,13 +87,6 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s); int ff_h263_decode_mb(MpegEncContext *s, int16_t block[6][64]); -/** - * Return the value of the 3-bit "source format" syntax element. - * This represents some standard picture dimensions or indicates that - * width&height are explicitly stored later. - */ -int av_const h263_get_picture_format(int width, int height); - void ff_clean_h263_qscales(MpegEncContext *s); int ff_h263_resync(MpegEncContext *s); void ff_h263_encode_motion(PutBitContext *pb, int val, int f_code); From 090cd1394fe7d6c422235c7c776f0fcbfdda1b57 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 02:14:13 +0100 Subject: [PATCH 520/894] avcodec/mpegvideo: Reindentation Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index be47ccb8ed..46e56ca08e 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -770,8 +770,8 @@ static int init_context_frame(MpegEncContext *s) return AVERROR(ENOMEM); #define ALLOCZ_ARRAYS(p, mult, numb) ((p) = av_calloc(numb, mult * sizeof(*(p)))) - if (s->codec_id == AV_CODEC_ID_MPEG4 || - (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + if (s->codec_id == AV_CODEC_ID_MPEG4 || + (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { int16_t (*tmp1)[2]; uint8_t *tmp2; if (!(tmp1 = ALLOCZ_ARRAYS(s->b_field_mv_table_base, 8, mv_table_size)) || @@ -782,19 +782,18 @@ static int init_context_frame(MpegEncContext *s) s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; tmp1 += s->mb_stride + 1; - for (i = 0; i < 2; i++) { - int j, k; - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { s->b_field_mv_table[i][j][k] = tmp1; tmp1 += mv_table_size; - } + } s->b_field_select_table[i][j] = tmp2; tmp2 += 2 * mv_table_size; + } } } } - } if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { From 9f906f3114d788c5047ed5c5d2d8a7bc73bed012 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 13:57:14 +0100 Subject: [PATCH 521/894] avcodec/mpegvideo_enc: Combine some checks Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index d33cf9477d..4adb95eca7 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3520,7 +3520,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) /* we need to initialize some time vars before we can encode B-frames */ // RAL: Condition added for MPEG1VIDEO - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->msmpeg4_version)) + if (s->out_format == FMT_MPEG1 || (s->h263_pred && !s->msmpeg4_version)) set_frame_distances(s); if(CONFIG_MPEG4_ENCODER && s->codec_id == AV_CODEC_ID_MPEG4) ff_set_mpeg4_time(s); @@ -3549,7 +3549,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) update_qscale(s); } - if(s->codec_id != AV_CODEC_ID_AMV && s->codec_id != AV_CODEC_ID_MJPEG){ + if (s->out_format != FMT_MJPEG) { if(s->q_chroma_intra_matrix != s->q_intra_matrix ) av_freep(&s->q_chroma_intra_matrix); if(s->q_chroma_intra_matrix16 != s->q_intra_matrix16) av_freep(&s->q_chroma_intra_matrix16); s->q_chroma_intra_matrix = s->q_intra_matrix; From a595717d214c892df05a955c935dd172924af47b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 14:43:58 +0100 Subject: [PATCH 522/894] avcodec/mpegvideo_enc: Remove some impossible branches Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 4adb95eca7..8865e38293 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -885,15 +885,16 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) ff_set_cmp(&s->mecc, s->mecc.ildct_cmp, avctx->ildct_cmp); ff_set_cmp(&s->mecc, s->mecc.frame_skip_cmp, s->frame_skip_cmp); - if (CONFIG_H261_ENCODER && s->out_format == FMT_H261) + if (CONFIG_H261_ENCODER && s->out_format == FMT_H261) { ff_h261_encode_init(s); - if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) - ff_h263_encode_init(s); - if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) - ff_msmpeg4_encode_init(s); - if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) - && s->out_format == FMT_MPEG1) + } else if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) + && s->out_format == FMT_MPEG1) { ff_mpeg1_encode_init(s); + } else if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) { + ff_h263_encode_init(s); + if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) + ff_msmpeg4_encode_init(s); + } /* init q matrix */ for (i = 0; i < 64; i++) { @@ -3695,7 +3696,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); s->qscale= 8; - } + if(s->codec_id == AV_CODEC_ID_AMV){ static const uint8_t y[32]={13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; static const uint8_t c[32]={14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; @@ -3715,8 +3716,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); s->qscale= 8; } - - if (s->out_format == FMT_SPEEDHQ) { + } else if (s->out_format == FMT_SPEEDHQ) { s->y_dc_scale_table= s->c_dc_scale_table= ff_mpeg2_dc_scale_table[3]; } From 3c9778d342e6709407e3906d680ebab3a3ecd754 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 14:47:57 +0100 Subject: [PATCH 523/894] avcodec/mpegvideo_enc: Reindent after the previous commit Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 8865e38293..128d1a327c 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3697,25 +3697,25 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); s->qscale= 8; - if(s->codec_id == AV_CODEC_ID_AMV){ - static const uint8_t y[32]={13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; - static const uint8_t c[32]={14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - for(i=1;i<64;i++){ - int j= s->idsp.idct_permutation[ff_zigzag_direct[i]]; + if (s->codec_id == AV_CODEC_ID_AMV) { + static const uint8_t y[32] = {13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; + static const uint8_t c[32] = {14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; + for (int i = 1; i < 64; i++) { + int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; - s->intra_matrix[j] = sp5x_qscale_five_quant_table[0][i]; - s->chroma_intra_matrix[j] = sp5x_qscale_five_quant_table[1][i]; + s->intra_matrix[j] = sp5x_qscale_five_quant_table[0][i]; + s->chroma_intra_matrix[j] = sp5x_qscale_five_quant_table[1][i]; + } + s->y_dc_scale_table = y; + s->c_dc_scale_table = c; + s->intra_matrix[0] = 13; + s->chroma_intra_matrix[0] = 14; + ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, + s->intra_matrix, s->intra_quant_bias, 8, 8, 1); + ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, + s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); + s->qscale = 8; } - s->y_dc_scale_table= y; - s->c_dc_scale_table= c; - s->intra_matrix[0] = 13; - s->chroma_intra_matrix[0] = 14; - ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, - s->intra_matrix, s->intra_quant_bias, 8, 8, 1); - ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, - s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); - s->qscale= 8; - } } else if (s->out_format == FMT_SPEEDHQ) { s->y_dc_scale_table= s->c_dc_scale_table= ff_mpeg2_dc_scale_table[3]; From 230646751d88e90a62a3b4a099d2f6e0e639be10 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 17:47:41 +0100 Subject: [PATCH 524/894] lavf/sdp: add const qualifiers where appropriate Declares that these structs are read-only for this code. --- libavformat/internal.h | 2 +- libavformat/rtp.c | 4 ++-- libavformat/rtp.h | 4 ++-- libavformat/sdp.c | 23 ++++++++++++----------- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index eb8239cd3f..64407b3640 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -557,7 +557,7 @@ uint64_t ff_parse_ntp_time(uint64_t ntp_ts); * @param fmt the AVFormatContext, which might contain options modifying * the generated SDP */ -void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, +void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt); diff --git a/libavformat/rtp.c b/libavformat/rtp.c index 38e234391b..c536a6f082 100644 --- a/libavformat/rtp.c +++ b/libavformat/rtp.c @@ -87,8 +87,8 @@ int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type) return -1; } -int ff_rtp_get_payload_type(AVFormatContext *fmt, - AVCodecParameters *par, int idx) +int ff_rtp_get_payload_type(const AVFormatContext *fmt, + const AVCodecParameters *par, int idx) { int i; const AVOutputFormat *ofmt = fmt ? fmt->oformat : NULL; diff --git a/libavformat/rtp.h b/libavformat/rtp.h index 389b824223..0c0e6089d7 100644 --- a/libavformat/rtp.h +++ b/libavformat/rtp.h @@ -38,8 +38,8 @@ * @param idx The stream index * @return The payload type (the 'PT' field in the RTP header). */ -int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecParameters *par, - int idx); +int ff_rtp_get_payload_type(const AVFormatContext *fmt, + const AVCodecParameters *par, int idx); /** * Initialize a codec context based on the payload type. diff --git a/libavformat/sdp.c b/libavformat/sdp.c index e83616cfbe..d7324352cb 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -151,7 +151,7 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url) } #define MAX_PSET_SIZE 1024 -static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) +static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par) { char *psets, *p; const uint8_t *r; @@ -222,7 +222,7 @@ static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) return psets; } -static char *extradata2psets_hevc(AVCodecParameters *par) +static char *extradata2psets_hevc(const AVCodecParameters *par) { char *psets; uint8_t *extradata = par->extradata; @@ -323,7 +323,7 @@ err: return NULL; } -static char *extradata2config(AVFormatContext *s, AVCodecParameters *par) +static char *extradata2config(AVFormatContext *s, const AVCodecParameters *par) { char *config; @@ -343,7 +343,7 @@ static char *extradata2config(AVFormatContext *s, AVCodecParameters *par) return config; } -static char *xiph_extradata2config(AVFormatContext *s, AVCodecParameters *par) +static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par) { uint8_t *config; char *encoded_config; @@ -413,7 +413,7 @@ xiph_fail: return NULL; } -static int latm_context2profilelevel(AVCodecParameters *par) +static int latm_context2profilelevel(const AVCodecParameters *par) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -442,7 +442,7 @@ static int latm_context2profilelevel(AVCodecParameters *par) return profile_level; } -static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) +static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *par) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -477,10 +477,11 @@ static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) return config; } -static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int payload_type, AVFormatContext *fmt) +static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st, + int payload_type, AVFormatContext *fmt) { char *config = NULL; - AVCodecParameters *p = st->codecpar; + const AVCodecParameters *p = st->codecpar; switch (p->codec_id) { case AV_CODEC_ID_DIRAC: @@ -762,11 +763,11 @@ static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int return buff; } -void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, +void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt) { - AVCodecParameters *p = st->codecpar; + const AVCodecParameters *p = st->codecpar; const char *type; int payload_type; @@ -863,7 +864,7 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) return AVERROR(ENOSYS); } -void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, +void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt) { From b0518f9977f6019c317e244ae6087db5ffbf0c9d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 18:00:07 +0100 Subject: [PATCH 525/894] lavf/sdp: reindent switch() according to our conventions --- libavformat/sdp.c | 516 +++++++++++++++++++++++----------------------- 1 file changed, 258 insertions(+), 258 deletions(-) diff --git a/libavformat/sdp.c b/libavformat/sdp.c index d7324352cb..53b4d27b12 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -484,278 +484,278 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st const AVCodecParameters *p = st->codecpar; switch (p->codec_id) { - case AV_CODEC_ID_DIRAC: - av_strlcatf(buff, size, "a=rtpmap:%d VC2/90000\r\n", payload_type); - break; - case AV_CODEC_ID_H264: { - int mode = 1; - if (fmt && fmt->oformat && fmt->oformat->priv_class && - av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) - mode = 0; - if (p->extradata_size) { - config = extradata2psets(fmt, p); - } - av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" - "a=fmtp:%d packetization-mode=%d%s\r\n", - payload_type, - payload_type, mode, config ? config : ""); - break; + case AV_CODEC_ID_DIRAC: + av_strlcatf(buff, size, "a=rtpmap:%d VC2/90000\r\n", payload_type); + break; + case AV_CODEC_ID_H264: { + int mode = 1; + if (fmt && fmt->oformat && fmt->oformat->priv_class && + av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) + mode = 0; + if (p->extradata_size) { + config = extradata2psets(fmt, p); } - case AV_CODEC_ID_H261: - { - const char *pic_fmt = NULL; - /* only QCIF and CIF are specified as supported in RFC 4587 */ - if (p->width == 176 && p->height == 144) - pic_fmt = "QCIF=1"; - else if (p->width == 352 && p->height == 288) - pic_fmt = "CIF=1"; - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type); - if (pic_fmt) - av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", payload_type, pic_fmt); - break; + av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" + "a=fmtp:%d packetization-mode=%d%s\r\n", + payload_type, + payload_type, mode, config ? config : ""); + break; + } + case AV_CODEC_ID_H261: + { + const char *pic_fmt = NULL; + /* only QCIF and CIF are specified as supported in RFC 4587 */ + if (p->width == 176 && p->height == 144) + pic_fmt = "QCIF=1"; + else if (p->width == 352 && p->height == 288) + pic_fmt = "CIF=1"; + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type); + if (pic_fmt) + av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", payload_type, pic_fmt); + break; + } + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + /* a=framesize is required by 3GPP TS 26.234 (PSS). It + * actually specifies the maximum video size, but we only know + * the current size. This is required for playback on Android + * stagefright and on Samsung bada. */ + if (!fmt || !fmt->oformat->priv_class || + !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || + p->codec_id == AV_CODEC_ID_H263P) + av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" + "a=framesize:%d %d-%d\r\n", + payload_type, + payload_type, p->width, p->height); + break; + case AV_CODEC_ID_HEVC: + if (p->extradata_size) + config = extradata2psets_hevc(p); + av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); + if (config) + av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", + payload_type, config); + break; + case AV_CODEC_ID_MPEG4: + if (p->extradata_size) { + config = extradata2config(fmt, p); } - case AV_CODEC_ID_H263: - case AV_CODEC_ID_H263P: - /* a=framesize is required by 3GPP TS 26.234 (PSS). It - * actually specifies the maximum video size, but we only know - * the current size. This is required for playback on Android - * stagefright and on Samsung bada. */ - if (!fmt || !fmt->oformat->priv_class || - !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || - p->codec_id == AV_CODEC_ID_H263P) - av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" - "a=framesize:%d %d-%d\r\n", - payload_type, - payload_type, p->width, p->height); - break; - case AV_CODEC_ID_HEVC: - if (p->extradata_size) - config = extradata2psets_hevc(p); - av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); - if (config) - av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", - payload_type, config); - break; - case AV_CODEC_ID_MPEG4: + av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" + "a=fmtp:%d profile-level-id=1%s\r\n", + payload_type, + payload_type, config ? config : ""); + break; + case AV_CODEC_ID_AAC: + if (fmt && fmt->oformat && fmt->oformat->priv_class && + av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { + config = latm_context2config(fmt, p); + if (!config) + return NULL; + av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" + "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", + payload_type, p->sample_rate, p->channels, + payload_type, latm_context2profilelevel(p), config); + } else { if (p->extradata_size) { config = extradata2config(fmt, p); - } - av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" - "a=fmtp:%d profile-level-id=1%s\r\n", - payload_type, - payload_type, config ? config : ""); - break; - case AV_CODEC_ID_AAC: - if (fmt && fmt->oformat && fmt->oformat->priv_class && - av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { - config = latm_context2config(fmt, p); - if (!config) - return NULL; - av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" - "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", - payload_type, p->sample_rate, p->channels, - payload_type, latm_context2profilelevel(p), config); } else { - if (p->extradata_size) { - config = extradata2config(fmt, p); - } else { - /* FIXME: maybe we can forge config information based on the - * codec parameters... - */ - av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); - return NULL; - } - if (!config) { - return NULL; - } - av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" - "a=fmtp:%d profile-level-id=1;" - "mode=AAC-hbr;sizelength=13;indexlength=3;" - "indexdeltalength=3%s\r\n", - payload_type, p->sample_rate, p->channels, - payload_type, config); + /* FIXME: maybe we can forge config information based on the + * codec parameters... + */ + av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); + return NULL; } - break; - case AV_CODEC_ID_PCM_S16BE: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n", - payload_type, - p->sample_rate, p->channels); - break; - case AV_CODEC_ID_PCM_S24BE: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d L24/%d/%d\r\n", - payload_type, - p->sample_rate, p->channels); - break; - case AV_CODEC_ID_PCM_MULAW: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", - payload_type, - p->sample_rate, p->channels); - break; - case AV_CODEC_ID_PCM_ALAW: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n", - payload_type, - p->sample_rate, p->channels); - break; - case AV_CODEC_ID_AMR_NB: - av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n" - "a=fmtp:%d octet-align=1\r\n", + if (!config) { + return NULL; + } + av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" + "a=fmtp:%d profile-level-id=1;" + "mode=AAC-hbr;sizelength=13;indexlength=3;" + "indexdeltalength=3%s\r\n", payload_type, p->sample_rate, p->channels, - payload_type); - break; - case AV_CODEC_ID_AMR_WB: - av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n" - "a=fmtp:%d octet-align=1\r\n", - payload_type, p->sample_rate, p->channels, - payload_type); - break; - case AV_CODEC_ID_VORBIS: - if (p->extradata_size) - config = xiph_extradata2config(fmt, p); - else - av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); - if (!config) - return NULL; - - av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n" - "a=fmtp:%d configuration=%s\r\n", - payload_type, p->sample_rate, p->channels, - payload_type, config); - break; - case AV_CODEC_ID_THEORA: { - const char *pix_fmt; - switch (p->format) { - case AV_PIX_FMT_YUV420P: - pix_fmt = "YCbCr-4:2:0"; - break; - case AV_PIX_FMT_YUV422P: - pix_fmt = "YCbCr-4:2:2"; - break; - case AV_PIX_FMT_YUV444P: - pix_fmt = "YCbCr-4:4:4"; - break; - default: - av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); - return NULL; - } - - if (p->extradata_size) - config = xiph_extradata2config(fmt, p); - else - av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n"); - if (!config) - return NULL; - - av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n" - "a=fmtp:%d delivery-method=inline; " - "width=%d; height=%d; sampling=%s; " - "configuration=%s\r\n", - payload_type, payload_type, - p->width, p->height, pix_fmt, config); - break; + payload_type, config); } - case AV_CODEC_ID_BITPACKED: - case AV_CODEC_ID_RAWVIDEO: { - const char *pix_fmt; - int bit_depth = 8; + break; + case AV_CODEC_ID_PCM_S16BE: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n", + payload_type, + p->sample_rate, p->channels); + break; + case AV_CODEC_ID_PCM_S24BE: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d L24/%d/%d\r\n", + payload_type, + p->sample_rate, p->channels); + break; + case AV_CODEC_ID_PCM_MULAW: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", + payload_type, + p->sample_rate, p->channels); + break; + case AV_CODEC_ID_PCM_ALAW: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n", + payload_type, + p->sample_rate, p->channels); + break; + case AV_CODEC_ID_AMR_NB: + av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n" + "a=fmtp:%d octet-align=1\r\n", + payload_type, p->sample_rate, p->channels, + payload_type); + break; + case AV_CODEC_ID_AMR_WB: + av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n" + "a=fmtp:%d octet-align=1\r\n", + payload_type, p->sample_rate, p->channels, + payload_type); + break; + case AV_CODEC_ID_VORBIS: + if (p->extradata_size) + config = xiph_extradata2config(fmt, p); + else + av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); + if (!config) + return NULL; - switch (p->format) { - case AV_PIX_FMT_UYVY422: - pix_fmt = "YCbCr-4:2:2"; - break; - case AV_PIX_FMT_YUV422P10: - pix_fmt = "YCbCr-4:2:2"; - bit_depth = 10; - break; - case AV_PIX_FMT_YUV420P: - pix_fmt = "YCbCr-4:2:0"; - break; - case AV_PIX_FMT_RGB24: - pix_fmt = "RGB"; - break; - case AV_PIX_FMT_BGR24: - pix_fmt = "BGR"; - break; - default: - av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); - return NULL; - } - - av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" - "a=fmtp:%d sampling=%s; " - "width=%d; height=%d; " - "depth=%d\r\n", - payload_type, payload_type, - pix_fmt, p->width, p->height, bit_depth); + av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n" + "a=fmtp:%d configuration=%s\r\n", + payload_type, p->sample_rate, p->channels, + payload_type, config); + break; + case AV_CODEC_ID_THEORA: { + const char *pix_fmt; + switch (p->format) { + case AV_PIX_FMT_YUV420P: + pix_fmt = "YCbCr-4:2:0"; break; - } - - case AV_CODEC_ID_VP8: - av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", - payload_type); + case AV_PIX_FMT_YUV422P: + pix_fmt = "YCbCr-4:2:2"; break; - case AV_CODEC_ID_VP9: - av_strlcatf(buff, size, "a=rtpmap:%d VP9/90000\r\n", - payload_type); - break; - case AV_CODEC_ID_MJPEG: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n", - payload_type); - break; - case AV_CODEC_ID_ADPCM_G722: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", - payload_type, - 8000, p->channels); - break; - case AV_CODEC_ID_ADPCM_G726: { - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d AAL2-G726-%d/%d\r\n", - payload_type, - p->bits_per_coded_sample*8, - p->sample_rate); - break; - } - case AV_CODEC_ID_ADPCM_G726LE: { - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n", - payload_type, - p->bits_per_coded_sample*8, - p->sample_rate); - break; - } - case AV_CODEC_ID_ILBC: - av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" - "a=fmtp:%d mode=%d\r\n", - payload_type, p->sample_rate, - payload_type, p->block_align == 38 ? 20 : 30); - break; - case AV_CODEC_ID_SPEEX: - av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", - payload_type, p->sample_rate); - break; - case AV_CODEC_ID_OPUS: - /* The opus RTP draft says that all opus streams MUST be declared - as stereo, to avoid negotiation failures. The actual number of - channels can change on a packet-by-packet basis. The number of - channels a receiver prefers to receive or a sender plans to send - can be declared via fmtp parameters (both default to mono), but - receivers MUST be able to receive and process stereo packets. */ - av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n", - payload_type); - if (p->channels == 2) { - av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", - payload_type); - } + case AV_PIX_FMT_YUV444P: + pix_fmt = "YCbCr-4:4:4"; break; default: - /* Nothing special to do here... */ + av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return NULL; + } + + if (p->extradata_size) + config = xiph_extradata2config(fmt, p); + else + av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n"); + if (!config) + return NULL; + + av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n" + "a=fmtp:%d delivery-method=inline; " + "width=%d; height=%d; sampling=%s; " + "configuration=%s\r\n", + payload_type, payload_type, + p->width, p->height, pix_fmt, config); + break; + } + case AV_CODEC_ID_BITPACKED: + case AV_CODEC_ID_RAWVIDEO: { + const char *pix_fmt; + int bit_depth = 8; + + switch (p->format) { + case AV_PIX_FMT_UYVY422: + pix_fmt = "YCbCr-4:2:2"; break; + case AV_PIX_FMT_YUV422P10: + pix_fmt = "YCbCr-4:2:2"; + bit_depth = 10; + break; + case AV_PIX_FMT_YUV420P: + pix_fmt = "YCbCr-4:2:0"; + break; + case AV_PIX_FMT_RGB24: + pix_fmt = "RGB"; + break; + case AV_PIX_FMT_BGR24: + pix_fmt = "BGR"; + break; + default: + av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return NULL; + } + + av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" + "a=fmtp:%d sampling=%s; " + "width=%d; height=%d; " + "depth=%d\r\n", + payload_type, payload_type, + pix_fmt, p->width, p->height, bit_depth); + break; + } + + case AV_CODEC_ID_VP8: + av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", + payload_type); + break; + case AV_CODEC_ID_VP9: + av_strlcatf(buff, size, "a=rtpmap:%d VP9/90000\r\n", + payload_type); + break; + case AV_CODEC_ID_MJPEG: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n", + payload_type); + break; + case AV_CODEC_ID_ADPCM_G722: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", + payload_type, + 8000, p->channels); + break; + case AV_CODEC_ID_ADPCM_G726: { + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d AAL2-G726-%d/%d\r\n", + payload_type, + p->bits_per_coded_sample*8, + p->sample_rate); + break; + } + case AV_CODEC_ID_ADPCM_G726LE: { + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n", + payload_type, + p->bits_per_coded_sample*8, + p->sample_rate); + break; + } + case AV_CODEC_ID_ILBC: + av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" + "a=fmtp:%d mode=%d\r\n", + payload_type, p->sample_rate, + payload_type, p->block_align == 38 ? 20 : 30); + break; + case AV_CODEC_ID_SPEEX: + av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", + payload_type, p->sample_rate); + break; + case AV_CODEC_ID_OPUS: + /* The opus RTP draft says that all opus streams MUST be declared + as stereo, to avoid negotiation failures. The actual number of + channels can change on a packet-by-packet basis. The number of + channels a receiver prefers to receive or a sender plans to send + can be declared via fmtp parameters (both default to mono), but + receivers MUST be able to receive and process stereo packets. */ + av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n", + payload_type); + if (p->channels == 2) { + av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", + payload_type); + } + break; + default: + /* Nothing special to do here... */ + break; } av_free(config); From fe31708eaa10af42507b8db773d5af5a56e1aff4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 4 Dec 2021 18:26:38 +0100 Subject: [PATCH 526/894] lavf/sdp: add more thorough error handling Return error codes when constructing a stream config fails, rather than just disregarding the failure and continuing. Propagate the error codes from av_sdp_create(). --- libavformat/internal.h | 7 +- libavformat/sdp.c | 190 +++++++++++++++++++++++++---------------- 2 files changed, 121 insertions(+), 76 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 64407b3640..92eeb82550 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -556,10 +556,11 @@ uint64_t ff_parse_ntp_time(uint64_t ntp_ts); * @param ttl the time to live of the stream, 0 if not multicast * @param fmt the AVFormatContext, which might contain options modifying * the generated SDP + * @return 0 on success, a negative error code on failure */ -void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, - const char *dest_addr, const char *dest_type, - int port, int ttl, AVFormatContext *fmt); +int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, + const char *dest_addr, const char *dest_type, + int port, int ttl, AVFormatContext *fmt); /** * Write a packet to another muxer than the one the user originally diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 53b4d27b12..ebde17bce4 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -151,7 +151,8 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url) } #define MAX_PSET_SIZE 1024 -static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par) +static int extradata2psets(AVFormatContext *s, const AVCodecParameters *par, + char **out) { char *psets, *p; const uint8_t *r; @@ -162,15 +163,18 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par) uint8_t *tmpbuf = NULL; const uint8_t *sps = NULL, *sps_end; + *out = NULL; + if (par->extradata_size > MAX_EXTRADATA_SIZE) { av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); - - return NULL; + return AVERROR_INVALIDDATA; } if (par->extradata[0] == 1) { - if (ff_avc_write_annexb_extradata(par->extradata, &extradata, - &extradata_size)) - return NULL; + int ret = ff_avc_write_annexb_extradata(par->extradata, &extradata, + &extradata_size); + if (ret < 0) + return ret; + tmpbuf = extradata; } @@ -178,7 +182,7 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par) if (!psets) { av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n"); av_free(tmpbuf); - return NULL; + return AVERROR(ENOMEM); } memcpy(psets, pset_string, strlen(pset_string)); p = psets + strlen(pset_string); @@ -203,11 +207,12 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par) sps_end = r1; } if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) { - av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r); + av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", + MAX_PSET_SIZE - (p - psets), r1 - r); av_free(psets); av_free(tmpbuf); - return NULL; + return AVERROR_INVALIDDATA; } p += strlen(p); r = r1; @@ -219,10 +224,11 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par) } av_free(tmpbuf); - return psets; + *out = psets; + return 0; } -static char *extradata2psets_hevc(const AVCodecParameters *par) +static int extradata2psets_hevc(const AVCodecParameters *par, char **out) { char *psets; uint8_t *extradata = par->extradata; @@ -231,7 +237,9 @@ static char *extradata2psets_hevc(const AVCodecParameters *par) int ps_pos[3] = { 0 }; static const char * const ps_names[3] = { "vps", "sps", "pps" }; int num_arrays, num_nalus; - int pos, i, j; + int pos, i, j, ret; + + *out = NULL; // Convert to hvcc format. Since we need to group multiple NALUs of // the same type, and we might need to convert from one format to the @@ -239,9 +247,13 @@ static char *extradata2psets_hevc(const AVCodecParameters *par) // format. if (par->extradata[0] != 1) { AVIOContext *pb; - if (avio_open_dyn_buf(&pb) < 0) - return NULL; - if (ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0) < 0) { + + ret = avio_open_dyn_buf(&pb); + if (ret < 0) + return ret; + + ret = ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); + if (ret < 0) { avio_close_dyn_buf(pb, &tmpbuf); goto err; } @@ -284,8 +296,11 @@ static char *extradata2psets_hevc(const AVCodecParameters *par) goto err; psets = av_mallocz(MAX_PSET_SIZE); - if (!psets) + if (!psets) { + ret = AVERROR(ENOMEM); goto err; + } + psets[0] = '\0'; for (i = 0; i < 3; i++) { @@ -316,40 +331,48 @@ static char *extradata2psets_hevc(const AVCodecParameters *par) } av_free(tmpbuf); - return psets; - + *out = psets; + return 0; err: + if (ret >= 0) + ret = AVERROR_INVALIDDATA; av_free(tmpbuf); - return NULL; + return ret; } -static char *extradata2config(AVFormatContext *s, const AVCodecParameters *par) +static int extradata2config(AVFormatContext *s, const AVCodecParameters *par, + char **out) { char *config; + *out = NULL; + if (par->extradata_size > MAX_EXTRADATA_SIZE) { av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); - - return NULL; + return AVERROR_INVALIDDATA; } config = av_malloc(10 + par->extradata_size * 2); if (!config) { av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); - return NULL; + return AVERROR(ENOMEM); } memcpy(config, "; config=", 9); ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0); - return config; + *out = config; + return 0; } -static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par) +static int xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par, + char **out) { uint8_t *config; char *encoded_config; const uint8_t *header_start[3]; int headers_len, header_len[3], config_len; - int first_header_size; + int first_header_size, ret; + + *out = NULL; switch (par->codec_id) { case AV_CODEC_ID_THEORA: @@ -360,14 +383,15 @@ static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters * break; default: av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n"); - return NULL; + return AVERROR(ENOSYS); } - if (avpriv_split_xiph_headers(par->extradata, par->extradata_size, - first_header_size, header_start, - header_len) < 0) { + ret = avpriv_split_xiph_headers(par->extradata, par->extradata_size, + first_header_size, header_start, + header_len); + if (ret < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); - return NULL; + return ret; } headers_len = header_len[0] + header_len[2]; @@ -405,12 +429,13 @@ static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters * config, config_len); av_free(config); - return encoded_config; + *out = encoded_config; + return 0; xiph_fail: av_log(s, AV_LOG_ERROR, "Not enough memory for configuration string\n"); - return NULL; + return AVERROR(ENOMEM); } static int latm_context2profilelevel(const AVCodecParameters *par) @@ -442,7 +467,8 @@ static int latm_context2profilelevel(const AVCodecParameters *par) return profile_level; } -static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *par) +static int latm_context2config(AVFormatContext *s, const AVCodecParameters *par, + char **out) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -452,12 +478,14 @@ static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *pa int rate_index; char *config; + *out = NULL; + for (rate_index = 0; rate_index < 16; rate_index++) if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate) break; if (rate_index == 16) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); - return NULL; + return AVERROR(ENOSYS); } config_byte[0] = 0x40; @@ -470,18 +498,20 @@ static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *pa config = av_malloc(6*2+1); if (!config) { av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); - return NULL; + return AVERROR(ENOMEM); } ff_data_to_hex(config, config_byte, 6, 1); - return config; + *out = config; + return 0; } -static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st, - int payload_type, AVFormatContext *fmt) +static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, + int payload_type, AVFormatContext *fmt) { char *config = NULL; const AVCodecParameters *p = st->codecpar; + int ret = 0; switch (p->codec_id) { case AV_CODEC_ID_DIRAC: @@ -493,7 +523,9 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) mode = 0; if (p->extradata_size) { - config = extradata2psets(fmt, p); + ret = extradata2psets(fmt, p, &config); + if (ret < 0) + return ret; } av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" "a=fmtp:%d packetization-mode=%d%s\r\n", @@ -530,8 +562,11 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st payload_type, p->width, p->height); break; case AV_CODEC_ID_HEVC: - if (p->extradata_size) - config = extradata2psets_hevc(p); + if (p->extradata_size) { + ret = extradata2psets_hevc(p, &config); + if (ret < 0) + return ret; + } av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); if (config) av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", @@ -539,7 +574,9 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st break; case AV_CODEC_ID_MPEG4: if (p->extradata_size) { - config = extradata2config(fmt, p); + ret = extradata2config(fmt, p, &config); + if (ret < 0) + return ret; } av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" "a=fmtp:%d profile-level-id=1%s\r\n", @@ -549,25 +586,24 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st case AV_CODEC_ID_AAC: if (fmt && fmt->oformat && fmt->oformat->priv_class && av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { - config = latm_context2config(fmt, p); - if (!config) - return NULL; + ret = latm_context2config(fmt, p, &config); + if (ret < 0) + return ret; av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", payload_type, p->sample_rate, p->channels, payload_type, latm_context2profilelevel(p), config); } else { if (p->extradata_size) { - config = extradata2config(fmt, p); + ret = extradata2config(fmt, p, &config); + if (ret < 0) + return ret; } else { /* FIXME: maybe we can forge config information based on the * codec parameters... */ av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); - return NULL; - } - if (!config) { - return NULL; + return AVERROR(ENOSYS); } av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" "a=fmtp:%d profile-level-id=1;" @@ -615,11 +651,13 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st break; case AV_CODEC_ID_VORBIS: if (p->extradata_size) - config = xiph_extradata2config(fmt, p); - else + ret = xiph_extradata2config(fmt, p, &config); + else { av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); - if (!config) - return NULL; + ret = AVERROR_INVALIDDATA; + } + if (ret < 0) + return ret; av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n" "a=fmtp:%d configuration=%s\r\n", @@ -640,15 +678,17 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st break; default: av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); - return NULL; + return AVERROR(ENOSYS); } if (p->extradata_size) - config = xiph_extradata2config(fmt, p); - else + ret = xiph_extradata2config(fmt, p, &config); + else { av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n"); - if (!config) - return NULL; + ret = AVERROR_INVALIDDATA; + } + if (ret < 0) + return ret; av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n" "a=fmtp:%d delivery-method=inline; " @@ -682,7 +722,7 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st break; default: av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); - return NULL; + return AVERROR(ENOSYS); } av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" @@ -760,12 +800,12 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st av_free(config); - return buff; + return 0; } -void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, - const char *dest_addr, const char *dest_type, - int port, int ttl, AVFormatContext *fmt) +int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, + const char *dest_addr, const char *dest_type, + int port, int ttl, AVFormatContext *fmt) { const AVCodecParameters *p = st->codecpar; const char *type; @@ -786,7 +826,7 @@ void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000); } - sdp_write_media_attributes(buff, size, st, payload_type, fmt); + return sdp_write_media_attributes(buff, size, st, payload_type, fmt); } int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) @@ -832,10 +872,13 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) ttl = 0; } for (j = 0; j < ac[i]->nb_streams; j++) { - ff_sdp_write_media(buf, size, ac[i]->streams[j], index++, - dst[0] ? dst : NULL, dst_type, - (port > 0) ? port + j * 2 : 0, - ttl, ac[i]); + int ret = ff_sdp_write_media(buf, size, ac[i]->streams[j], index++, + dst[0] ? dst : NULL, dst_type, + (port > 0) ? port + j * 2 : 0, + ttl, ac[i]); + if (ret < 0) + return ret; + if (port <= 0) { av_strlcatf(buf, size, "a=control:streamid=%d\r\n", i + j); @@ -864,9 +907,10 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) return AVERROR(ENOSYS); } -void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, - const char *dest_addr, const char *dest_type, - int port, int ttl, AVFormatContext *fmt) +int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, + const char *dest_addr, const char *dest_type, + int port, int ttl, AVFormatContext *fmt) { + return AVERROR(ENOSYS); } #endif From 67aceaf4ad641a4d34c3ec70b532efdc60483e3d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 13 Dec 2021 11:23:52 +0100 Subject: [PATCH 527/894] lavc/encode: improve the empty frame check Test for buf[0] rather than data[0] (which is broken for some hwaccel formats). --- libavcodec/encode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index dd25cf999b..5575cf23db 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -366,7 +366,7 @@ int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame if (avci->draining) return AVERROR_EOF; - if (avci->buffer_frame->data[0]) + if (avci->buffer_frame->buf[0]) return AVERROR(EAGAIN); if (!frame) { From b780b6db649e693fb1aaebe0da6006a1a5055466 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 13 Dec 2021 11:43:16 +0100 Subject: [PATCH 528/894] lavc/encode: set frame_number for encoders using receive_packet() It is currently set in encode_simple_internal(), which is only called for encoders using the "simple" encoding API. --- libavcodec/encode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 5575cf23db..618be0573d 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -247,11 +247,8 @@ end: if (ret < 0 || !got_packet) av_packet_unref(avpkt); - if (frame) { - if (!ret) - avctx->frame_number++; + if (frame) av_frame_unref(frame); - } if (got_packet) // Encoders must always return ref-counted buffers. @@ -383,6 +380,8 @@ int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame return ret; } + avctx->frame_number++; + return 0; } From 68457c1e85122ffcadb0c909070dd210095fd2cd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Jul 2020 23:34:15 +0200 Subject: [PATCH 529/894] avcodec/alacdsp: fix integer overflow in decorrelate_stereo() Fixes: signed integer overflow: -16777216 * 131 cannot be represented in type 'int' Fixes: 23835/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ALAC_fuzzer-5669943160078336 Fixes: 41101/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ALAC_fuzzer-4636330705944576 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/alacdsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/alacdsp.c b/libavcodec/alacdsp.c index 9996eb4319..8718d1b6b1 100644 --- a/libavcodec/alacdsp.c +++ b/libavcodec/alacdsp.c @@ -34,7 +34,7 @@ static void decorrelate_stereo(int32_t *buffer[2], int nb_samples, a = buffer[0][i]; b = buffer[1][i]; - a -= (b * decorr_left_weight) >> decorr_shift; + a -= (int)(b * (unsigned)decorr_left_weight) >> decorr_shift; b += a; buffer[0][i] = b; From 1c49d74fad3a996e08a6b96db59ed5179f8aa373 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 15 Dec 2021 10:26:22 +0100 Subject: [PATCH 530/894] avcodec/cdgraphics: unbreak rendering of vertical scrolling --- libavcodec/cdgraphics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index 731d800666..c9e265fa53 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -218,7 +218,7 @@ static void cdg_scroll(CDGraphicsContext *cc, uint8_t *data, /// find the difference and save the offset for cdg_tile_block usage hinc = h_off - cc->hscroll; - vinc = v_off - cc->vscroll; + vinc = cc->vscroll - v_off; cc->hscroll = h_off; cc->vscroll = v_off; From 8718f8cfafd28a07faf88b5a3427c04cc6fa663b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 16 Dec 2021 11:31:59 +0100 Subject: [PATCH 531/894] avcodec/cdgraphics: fix transparency handling --- libavcodec/cdgraphics.c | 13 +- tests/ref/fate/cdgraphics | 398 +++++++++++++++++++------------------- 2 files changed, 206 insertions(+), 205 deletions(-) diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index c9e265fa53..06f8392094 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -68,7 +68,7 @@ typedef struct CDGraphicsContext { AVFrame *frame; int hscroll; int vscroll; - int transparency; + uint8_t alpha[CDG_PALETTE_SIZE]; int cleared; } CDGraphicsContext; @@ -79,7 +79,9 @@ static av_cold int cdg_decode_init(AVCodecContext *avctx) cc->frame = av_frame_alloc(); if (!cc->frame) return AVERROR(ENOMEM); - cc->transparency = -1; + + for (int i = 0; i < CDG_PALETTE_SIZE; i++) + cc->alpha[i] = 0xFFU; avctx->pix_fmt = AV_PIX_FMT_PAL8; return ff_set_dimensions(avctx, CDG_FULL_WIDTH, CDG_FULL_HEIGHT); @@ -120,9 +122,7 @@ static void cdg_load_palette(CDGraphicsContext *cc, uint8_t *data, int low) r = ((color >> 8) & 0x000F) * 17; g = ((color >> 4) & 0x000F) * 17; b = ((color ) & 0x000F) * 17; - palette[i + array_offset] = 0xFFU << 24 | r << 16 | g << 8 | b; - if (cc->transparency >= 0) - palette[cc->transparency] &= 0xFFFFFF; + palette[i + array_offset] = cc->alpha[i + array_offset] << 24 | r << 16 | g << 8 | b; } cc->frame->palette_has_changed = 1; } @@ -346,7 +346,8 @@ static int cdg_decode_frame(AVCodecContext *avctx, return ret; break; case CDG_INST_TRANSPARENT_COL: - cc->transparency = cdg_data[0] & 0xF; + for (int i = 0; i < CDG_PALETTE_SIZE; i++) + cc->alpha[i] = 255 - ((cdg_data[i] & 0x3f) << 2); break; default: break; diff --git a/tests/ref/fate/cdgraphics b/tests/ref/fate/cdgraphics index f079bd4df0..9ffe129397 100644 --- a/tests/ref/fate/cdgraphics +++ b/tests/ref/fate/cdgraphics @@ -16,202 +16,202 @@ 0, 10, 10, 1, 259200, 0x6779f55d 0, 11, 11, 1, 259200, 0x6779f55d 0, 12, 12, 1, 259200, 0x6779f55d -0, 13, 13, 1, 259200, 0xf33cc0c4 -0, 14, 14, 1, 259200, 0xf33cc0c4 -0, 15, 15, 1, 259200, 0xf33cc0c4 -0, 16, 16, 1, 259200, 0x098280da -0, 17, 17, 1, 259200, 0x098280da -0, 18, 18, 1, 259200, 0x098280da -0, 19, 19, 1, 259200, 0x098280da -0, 20, 20, 1, 259200, 0x098280da -0, 21, 21, 1, 259200, 0x098280da -0, 22, 22, 1, 259200, 0x098280da -0, 23, 23, 1, 259200, 0x098280da -0, 24, 24, 1, 259200, 0x098280da -0, 25, 25, 1, 259200, 0x098280da -0, 26, 26, 1, 259200, 0x098280da -0, 27, 27, 1, 259200, 0x098280da -0, 28, 28, 1, 259200, 0x098280da -0, 29, 29, 1, 259200, 0x098280da -0, 30, 30, 1, 259200, 0x098280da -0, 31, 31, 1, 259200, 0x098280da -0, 32, 32, 1, 259200, 0xf33cc0c4 -0, 33, 33, 1, 259200, 0xa389d0b4 -0, 34, 34, 1, 259200, 0xecf1f094 -0, 35, 35, 1, 259200, 0xe7171c77 -0, 37, 37, 1, 259200, 0xf9d72c67 -0, 38, 38, 1, 259200, 0x7932583b -0, 40, 40, 1, 259200, 0x1c618c07 -0, 41, 41, 1, 259200, 0x7e88c1d1 -0, 43, 43, 1, 259200, 0x2c5df59d -0, 44, 44, 1, 259200, 0xa78f435e -0, 46, 46, 1, 259200, 0xb96e5948 -0, 47, 47, 1, 259200, 0x85c1653c -0, 49, 49, 1, 259200, 0xefdc930e -0, 50, 50, 1, 259200, 0xea24bee2 -0, 52, 52, 1, 259200, 0x8feef8a8 -0, 53, 53, 1, 259200, 0x8a7b02ad -0, 55, 55, 1, 259200, 0xe41b2689 -0, 56, 56, 1, 259200, 0x007d307f -0, 58, 58, 1, 259200, 0xb0c9802f -0, 59, 59, 1, 259200, 0xb50c941b -0, 61, 61, 1, 259200, 0xdf7dc7e7 -0, 62, 62, 1, 259200, 0xbaac01bc -0, 64, 64, 1, 259200, 0x1ef70db0 -0, 65, 65, 1, 259200, 0xeeab4b72 -0, 67, 67, 1, 259200, 0x0eaf7d40 -0, 68, 68, 1, 259200, 0xc7bec4f8 -0, 70, 70, 1, 259200, 0xa506caf2 -0, 71, 71, 1, 259200, 0x268808c3 -0, 73, 73, 1, 259200, 0xebd90ebd -0, 74, 74, 1, 259200, 0x8d792aa1 -0, 76, 76, 1, 259200, 0x960d3a91 -0, 77, 77, 1, 259200, 0xf0395e6d -0, 79, 79, 1, 259200, 0x3d0e8645 -0, 80, 80, 1, 259200, 0x88bc9a31 -0, 82, 82, 1, 259200, 0xda37c209 -0, 83, 83, 1, 259200, 0xafa6c803 -0, 85, 85, 1, 259200, 0xdc58f5d5 -0, 86, 86, 1, 259200, 0x1a5ffbcf -0, 88, 88, 1, 259200, 0xc8872bae -0, 89, 89, 1, 259200, 0xc5472dac -0, 91, 91, 1, 259200, 0xd54e5f7a -0, 92, 92, 1, 259200, 0xf4576574 -0, 94, 94, 1, 259200, 0xdefaad2c -0, 95, 95, 1, 259200, 0xca44c316 -0, 97, 97, 1, 259200, 0x8102d504 -0, 98, 98, 1, 259200, 0xe0c8fcdc -0, 100, 100, 1, 259200, 0x53c100e7 -0, 101, 101, 1, 259200, 0x8de628bf -0, 103, 103, 1, 259200, 0x86f92eb9 -0, 104, 104, 1, 259200, 0x13c66285 -0, 106, 106, 1, 259200, 0xe5766c7b -0, 107, 107, 1, 259200, 0x3ddb9453 -0, 109, 109, 1, 259200, 0x39559a4d -0, 110, 110, 1, 259200, 0x507da443 -0, 112, 112, 1, 259200, 0x3b8dedf9 -0, 113, 113, 1, 259200, 0x55c9fde9 -0, 115, 115, 1, 259200, 0x7c43ffe7 -0, 116, 116, 1, 259200, 0xdf2c31c4 -0, 118, 118, 1, 259200, 0x144735c0 -0, 119, 119, 1, 259200, 0x9a716b8a -0, 121, 121, 1, 259200, 0x5ab08174 -0, 122, 122, 1, 259200, 0x06dcb540 -0, 124, 124, 1, 259200, 0x0d09b93c -0, 125, 125, 1, 259200, 0x5abce70e -0, 127, 127, 1, 259200, 0x38a4ed08 -0, 128, 128, 1, 259200, 0x427b30d3 -0, 130, 130, 1, 259200, 0x7f8d34cf -0, 131, 131, 1, 259200, 0xf5613cc7 -0, 133, 133, 1, 259200, 0x5086748f -0, 134, 134, 1, 259200, 0x7da8788b -0, 136, 136, 1, 259200, 0x79c8946f -0, 137, 137, 1, 259200, 0x65d9bc47 -0, 139, 139, 1, 259200, 0x3f5a0012 -0, 140, 140, 1, 259200, 0x4d9713fe -0, 142, 142, 1, 259200, 0x917839d8 -0, 143, 143, 1, 259200, 0x92624dc4 -0, 145, 145, 1, 259200, 0x465c739e -0, 146, 146, 1, 259200, 0x21137f92 -0, 148, 148, 1, 259200, 0xd677a76a -0, 149, 149, 1, 259200, 0xe1efb35e -0, 151, 151, 1, 259200, 0xd2d6d73a -0, 152, 152, 1, 259200, 0x06a8f31e -0, 154, 154, 1, 259200, 0x8aaf1d03 -0, 155, 155, 1, 259200, 0x9e0a42dd -0, 157, 157, 1, 259200, 0x1f7268b7 -0, 158, 158, 1, 259200, 0x1a3c6cb3 -0, 160, 160, 1, 259200, 0x5607aa75 -0, 161, 161, 1, 259200, 0xa19ebc63 -0, 163, 163, 1, 259200, 0x9dbaf42b -0, 164, 164, 1, 259200, 0x2d06fe21 -0, 166, 166, 1, 259200, 0x960e2c02 -0, 167, 167, 1, 259200, 0x04f935f8 -0, 169, 169, 1, 259200, 0x488143ea -0, 170, 170, 1, 259200, 0xcb515bd2 -0, 172, 172, 1, 259200, 0xa27c85a8 -0, 173, 173, 1, 259200, 0x3bb38da0 -0, 175, 175, 1, 259200, 0x39d9b17c -0, 176, 176, 1, 259200, 0x3fbcbd70 -0, 178, 178, 1, 259200, 0xbc19e548 -0, 179, 179, 1, 259200, 0x29400735 -0, 181, 181, 1, 259200, 0x21612d0f -0, 182, 182, 1, 259200, 0x66943705 -0, 184, 184, 1, 259200, 0x9efa6ccf -0, 185, 185, 1, 259200, 0x3b4180bb -0, 187, 187, 1, 259200, 0x9a8aa695 -0, 188, 188, 1, 259200, 0x6529b883 -0, 190, 190, 1, 259200, 0x6e1aec4f -0, 191, 191, 1, 259200, 0x3ebc2426 -0, 193, 193, 1, 259200, 0xff6e3a10 -0, 194, 194, 1, 259200, 0x70f05dec -0, 196, 196, 1, 259200, 0x853777d2 -0, 197, 197, 1, 259200, 0x05ea97b2 -0, 199, 199, 1, 259200, 0x03f3a7a2 -0, 200, 200, 1, 259200, 0xf4f7cb7e -0, 202, 202, 1, 259200, 0xd411db6e -0, 203, 203, 1, 259200, 0xfa3afb4e -0, 205, 205, 1, 259200, 0x0a451b3d -0, 206, 206, 1, 259200, 0x94624117 -0, 208, 208, 1, 259200, 0x00996ceb -0, 209, 209, 1, 259200, 0x8c898ccb -0, 211, 211, 1, 259200, 0x5d2496c1 -0, 212, 212, 1, 259200, 0x4f5fce89 -0, 214, 214, 1, 259200, 0xf6a0e671 -0, 215, 215, 1, 259200, 0xcf6f184e -0, 217, 217, 1, 259200, 0x66e2283e -0, 218, 218, 1, 259200, 0x7cd25016 -0, 220, 220, 1, 259200, 0xc2e05a0c -0, 221, 221, 1, 259200, 0x33b767fe -0, 223, 223, 1, 259200, 0x6f5583e2 -0, 224, 224, 1, 259200, 0x19f3a9bc -0, 226, 226, 1, 259200, 0xb3f3b5b0 -0, 227, 227, 1, 259200, 0x6417d590 -0, 229, 229, 1, 259200, 0x7130e580 -0, 230, 230, 1, 259200, 0x4558096b -0, 232, 232, 1, 259200, 0x920c3143 -0, 233, 233, 1, 259200, 0xb7e75123 -0, 235, 235, 1, 259200, 0x38e46113 -0, 236, 236, 1, 259200, 0x96ba90e3 -0, 238, 238, 1, 259200, 0xc65faac9 -0, 239, 239, 1, 259200, 0x7260caa9 -0, 241, 241, 1, 259200, 0x4983cca7 -0, 242, 242, 1, 259200, 0xc04ddc97 -0, 244, 244, 1, 259200, 0x52de0082 -0, 245, 245, 1, 259200, 0xb1cb1c66 -0, 247, 247, 1, 259200, 0x273b364c -0, 248, 248, 1, 259200, 0xd26a661c -0, 250, 250, 1, 259200, 0x9a9599e8 -0, 251, 251, 1, 259200, 0x2e16b5cc -0, 253, 253, 1, 259200, 0x2d4ec9b8 -0, 254, 254, 1, 259200, 0x32d8e998 -0, 256, 256, 1, 259200, 0x5182f988 -0, 257, 257, 1, 259200, 0x48d7157b -0, 259, 259, 1, 259200, 0xa50f335d -0, 260, 260, 1, 259200, 0x3f274f41 -0, 262, 262, 1, 259200, 0xe9776b25 -0, 263, 263, 1, 259200, 0x76728709 -0, 265, 265, 1, 259200, 0x1960a0ef -0, 266, 266, 1, 259200, 0x3d3acac5 -0, 268, 268, 1, 259200, 0x1c6aeaa5 -0, 269, 269, 1, 259200, 0x8bc0148a -0, 271, 271, 1, 259200, 0xa2a72a74 -0, 272, 272, 1, 259200, 0x77db4658 -0, 274, 274, 1, 259200, 0x63705a44 -0, 275, 275, 1, 259200, 0x30db8c12 -0, 277, 277, 1, 259200, 0x32f5a3fa -0, 278, 278, 1, 259200, 0x0107d7c6 -0, 280, 280, 1, 259200, 0xe14707a5 -0, 281, 281, 1, 259200, 0xed7e3379 -0, 283, 283, 1, 259200, 0x55bc416b -0, 284, 284, 1, 259200, 0x1cf1614b -0, 286, 286, 1, 259200, 0x2d507b31 -0, 287, 287, 1, 259200, 0x3fbbaefd -0, 289, 289, 1, 259200, 0x8608d6d5 -0, 290, 290, 1, 259200, 0x169d00ba -0, 292, 292, 1, 259200, 0x7d0b209a -0, 293, 293, 1, 259200, 0xd5943c7e -0, 295, 295, 1, 259200, 0x94e25664 -0, 296, 296, 1, 259200, 0x97447e3c -0, 298, 298, 1, 259200, 0x68bc8436 -0, 299, 299, 1, 259200, 0xb7ee9426 +0, 13, 13, 1, 259200, 0x6779f55d +0, 14, 14, 1, 259200, 0x6779f55d +0, 15, 15, 1, 259200, 0x6779f55d +0, 16, 16, 1, 259200, 0x29aeb27e +0, 17, 17, 1, 259200, 0x29aeb27e +0, 18, 18, 1, 259200, 0x29aeb27e +0, 19, 19, 1, 259200, 0x29aeb27e +0, 20, 20, 1, 259200, 0x29aeb27e +0, 21, 21, 1, 259200, 0x29aeb27e +0, 22, 22, 1, 259200, 0x29aeb27e +0, 23, 23, 1, 259200, 0x29aeb27e +0, 24, 24, 1, 259200, 0x29aeb27e +0, 25, 25, 1, 259200, 0x29aeb27e +0, 26, 26, 1, 259200, 0x29aeb27e +0, 27, 27, 1, 259200, 0x29aeb27e +0, 28, 28, 1, 259200, 0x29aeb27e +0, 29, 29, 1, 259200, 0x29aeb27e +0, 30, 30, 1, 259200, 0x29aeb27e +0, 31, 31, 1, 259200, 0x29aeb27e +0, 32, 32, 1, 259200, 0x6779f55d +0, 33, 33, 1, 259200, 0xcc9cfd55 +0, 34, 34, 1, 259200, 0x0b670d54 +0, 35, 35, 1, 259200, 0x2c45233e +0, 37, 37, 1, 259200, 0x42a92b36 +0, 38, 38, 1, 259200, 0xa61a4120 +0, 40, 40, 1, 259200, 0x22065b06 +0, 41, 41, 1, 259200, 0x7f0775eb +0, 43, 43, 1, 259200, 0x00468fd1 +0, 44, 44, 1, 259200, 0xfd4bb6aa +0, 46, 46, 1, 259200, 0x182fc19f +0, 47, 47, 1, 259200, 0x8814c799 +0, 49, 49, 1, 259200, 0xe28dde82 +0, 50, 50, 1, 259200, 0x038bf46c +0, 52, 52, 1, 259200, 0x8597115e +0, 53, 53, 1, 259200, 0x8b001659 +0, 55, 55, 1, 259200, 0xd5192847 +0, 56, 56, 1, 259200, 0xeb652d42 +0, 58, 58, 1, 259200, 0x84ae551a +0, 59, 59, 1, 259200, 0x171c5f10 +0, 61, 61, 1, 259200, 0xd69a78f6 +0, 62, 62, 1, 259200, 0xf36095d9 +0, 64, 64, 1, 259200, 0x2f509bd3 +0, 65, 65, 1, 259200, 0x49a1bab4 +0, 67, 67, 1, 259200, 0x8248d39b +0, 68, 68, 1, 259200, 0x9969f777 +0, 70, 70, 1, 259200, 0x0cf6fa74 +0, 71, 71, 1, 259200, 0x801f1964 +0, 73, 73, 1, 259200, 0xe7a91c61 +0, 74, 74, 1, 259200, 0xcf402a53 +0, 76, 76, 1, 259200, 0xe08e324b +0, 77, 77, 1, 259200, 0x2afc4439 +0, 79, 79, 1, 259200, 0x71e95825 +0, 80, 80, 1, 259200, 0xa805621b +0, 82, 82, 1, 259200, 0x71547607 +0, 83, 83, 1, 259200, 0x60ed7904 +0, 85, 85, 1, 259200, 0x1cb98fed +0, 86, 86, 1, 259200, 0xc08f92ea +0, 88, 88, 1, 259200, 0x3ebeaad2 +0, 89, 89, 1, 259200, 0xbeb7abd1 +0, 91, 91, 1, 259200, 0xef67c4b8 +0, 92, 92, 1, 259200, 0x03dcc7b5 +0, 94, 94, 1, 259200, 0xb3b8eb91 +0, 95, 95, 1, 259200, 0x3b4af686 +0, 97, 97, 1, 259200, 0xa546ff7d +0, 98, 98, 1, 259200, 0xf5b31378 +0, 100, 100, 1, 259200, 0x32781576 +0, 101, 101, 1, 259200, 0xf00d2962 +0, 103, 103, 1, 259200, 0xf1782c5f +0, 104, 104, 1, 259200, 0x62334645 +0, 106, 106, 1, 259200, 0x53354b40 +0, 107, 107, 1, 259200, 0x9fea5f2c +0, 109, 109, 1, 259200, 0x22906229 +0, 110, 110, 1, 259200, 0xb63f6724 +0, 112, 112, 1, 259200, 0x68018bff +0, 113, 113, 1, 259200, 0x822393f7 +0, 115, 115, 1, 259200, 0x170894f6 +0, 116, 116, 1, 259200, 0x7129addd +0, 118, 118, 1, 259200, 0x8ef0afdb +0, 119, 119, 1, 259200, 0x7dfacac0 +0, 121, 121, 1, 259200, 0x6fffd5b5 +0, 122, 122, 1, 259200, 0x7062ef9b +0, 124, 124, 1, 259200, 0xf6b2f199 +0, 125, 125, 1, 259200, 0x43060891 +0, 127, 127, 1, 259200, 0xb6d40b8e +0, 128, 128, 1, 259200, 0x73182d6c +0, 130, 130, 1, 259200, 0x94e22f6a +0, 131, 131, 1, 259200, 0xd64e3366 +0, 133, 133, 1, 259200, 0x31764f4a +0, 134, 134, 1, 259200, 0x4b485148 +0, 136, 136, 1, 259200, 0x601f5f3a +0, 137, 137, 1, 259200, 0xf6aa7326 +0, 139, 139, 1, 259200, 0x9ac39504 +0, 140, 140, 1, 259200, 0x322e9efa +0, 142, 142, 1, 259200, 0x7308b1e7 +0, 143, 143, 1, 259200, 0x83c2bbdd +0, 145, 145, 1, 259200, 0xfca1ceca +0, 146, 146, 1, 259200, 0x73c7d4c4 +0, 148, 148, 1, 259200, 0xef03e8b0 +0, 149, 149, 1, 259200, 0xfe82eeaa +0, 151, 151, 1, 259200, 0x944600a7 +0, 152, 152, 1, 259200, 0x44f60e99 +0, 154, 154, 1, 259200, 0xa9242384 +0, 155, 155, 1, 259200, 0xd1bb3671 +0, 157, 157, 1, 259200, 0x3160495e +0, 158, 158, 1, 259200, 0x32064b5c +0, 160, 160, 1, 259200, 0x825b6a3d +0, 161, 161, 1, 259200, 0xb6cb7334 +0, 163, 163, 1, 259200, 0xe2678f18 +0, 164, 164, 1, 259200, 0x32379413 +0, 166, 166, 1, 259200, 0x0c2eaafc +0, 167, 167, 1, 259200, 0xcbb7aff7 +0, 169, 169, 1, 259200, 0x78e6b6f0 +0, 170, 170, 1, 259200, 0xcdd4c2e4 +0, 172, 172, 1, 259200, 0xdb94d7cf +0, 173, 173, 1, 259200, 0x2eb9dbcb +0, 175, 175, 1, 259200, 0x4b15edb9 +0, 176, 176, 1, 259200, 0xd7c2f3b3 +0, 178, 178, 1, 259200, 0xb68207ae +0, 179, 179, 1, 259200, 0x88be189d +0, 181, 181, 1, 259200, 0xa3b82b8a +0, 182, 182, 1, 259200, 0xce743085 +0, 184, 184, 1, 259200, 0x969c4b6a +0, 185, 185, 1, 259200, 0xf4fd5560 +0, 187, 187, 1, 259200, 0x439a684d +0, 188, 188, 1, 259200, 0x378e7144 +0, 190, 190, 1, 259200, 0xe64c8b2a +0, 191, 191, 1, 259200, 0xfc2ba70e +0, 193, 193, 1, 259200, 0xee71b203 +0, 194, 194, 1, 259200, 0xc47bc3f1 +0, 196, 196, 1, 259200, 0xe3c5d0e4 +0, 197, 197, 1, 259200, 0x3e2ee0d4 +0, 199, 199, 1, 259200, 0xca2fe8cc +0, 200, 200, 1, 259200, 0x6009faba +0, 202, 202, 1, 259200, 0x5c9a02c1 +0, 203, 203, 1, 259200, 0x09be12b1 +0, 205, 205, 1, 259200, 0x2bc422a1 +0, 206, 206, 1, 259200, 0x8fbc358e +0, 208, 208, 1, 259200, 0xe99b4b78 +0, 209, 209, 1, 259200, 0x49aa5b68 +0, 211, 211, 1, 259200, 0x3a1a6063 +0, 212, 212, 1, 259200, 0xe0be7c47 +0, 214, 214, 1, 259200, 0xc7ec883b +0, 215, 215, 1, 259200, 0xdd00a122 +0, 217, 217, 1, 259200, 0x35c5a91a +0, 218, 218, 1, 259200, 0x6147bd06 +0, 220, 220, 1, 259200, 0x0c78c201 +0, 221, 221, 1, 259200, 0xd038c8fa +0, 223, 223, 1, 259200, 0x04ddd6ec +0, 224, 224, 1, 259200, 0x790ee9d9 +0, 226, 226, 1, 259200, 0xcfd1efd3 +0, 227, 227, 1, 259200, 0xc1ebffc3 +0, 229, 229, 1, 259200, 0x558307ca +0, 230, 230, 1, 259200, 0x5ce019b8 +0, 232, 232, 1, 259200, 0xa3c42da4 +0, 233, 233, 1, 259200, 0x50c13d94 +0, 235, 235, 1, 259200, 0x9e3c458c +0, 236, 236, 1, 259200, 0xf4335d74 +0, 238, 238, 1, 259200, 0x213b6a67 +0, 239, 239, 1, 259200, 0x913c7a57 +0, 241, 241, 1, 259200, 0x7e6e7b56 +0, 242, 242, 1, 259200, 0xc6d7834e +0, 244, 244, 1, 259200, 0x2d70953c +0, 245, 245, 1, 259200, 0xf3a6a32e +0, 247, 247, 1, 259200, 0x438cb021 +0, 248, 248, 1, 259200, 0x4037c809 +0, 250, 250, 1, 259200, 0xce92e1ef +0, 251, 251, 1, 259200, 0x2f21efe1 +0, 253, 253, 1, 259200, 0x3f02f9d7 +0, 254, 254, 1, 259200, 0x5bcf09d6 +0, 256, 256, 1, 259200, 0x782811ce +0, 257, 257, 1, 259200, 0x0aa11fc0 +0, 259, 259, 1, 259200, 0xd11d2eb1 +0, 260, 260, 1, 259200, 0xb4f03ca3 +0, 262, 262, 1, 259200, 0x20ee4a95 +0, 263, 263, 1, 259200, 0x7e2b5887 +0, 265, 265, 1, 259200, 0xe4c1657a +0, 266, 266, 1, 259200, 0x98e07a65 +0, 268, 268, 1, 259200, 0xa2808a55 +0, 269, 269, 1, 259200, 0x7c5d9f40 +0, 271, 271, 1, 259200, 0x99b6aa35 +0, 272, 272, 1, 259200, 0x9b17b827 +0, 274, 274, 1, 259200, 0x212ec21d +0, 275, 275, 1, 259200, 0x3090db04 +0, 277, 277, 1, 259200, 0x4523e6f8 +0, 278, 278, 1, 259200, 0x567900ed +0, 280, 280, 1, 259200, 0xeda518d5 +0, 281, 281, 1, 259200, 0x97932ebf +0, 283, 283, 1, 259200, 0xd70e35b8 +0, 284, 284, 1, 259200, 0x54b845a8 +0, 286, 286, 1, 259200, 0x720e529b +0, 287, 287, 1, 259200, 0x25986c81 +0, 289, 289, 1, 259200, 0xe941806d +0, 290, 290, 1, 259200, 0xd3b69558 +0, 292, 292, 1, 259200, 0x2104a548 +0, 293, 293, 1, 259200, 0xe408b33a +0, 295, 295, 1, 259200, 0x58ddc02d +0, 296, 296, 1, 259200, 0x7a98d419 +0, 298, 298, 1, 259200, 0xe82ed716 +0, 299, 299, 1, 259200, 0x1cdadf0e From a8a7c5d502a851d16c4668e03bff12d0e16c32b8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 Nov 2021 15:12:20 +0100 Subject: [PATCH 532/894] avcodec/thd: fix special stereo support --- libavcodec/mlpdec.c | 4 +++- libavcodec/mlpenc.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 780ed5b7b6..29fac54542 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -408,7 +408,9 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) mh.stream_type); return AVERROR_PATCHWELCOME; } - if (mh.channel_modifier_thd_stream0 == THD_CH_MODIFIER_STEREO) + if (mh.channels_thd_stream1 == 2 && + mh.channels_thd_stream2 == 2 && + m->avctx->channels == 2) m->substream[0].mask = AV_CH_LAYOUT_STEREO; if ((substr = (mh.num_substreams > 1))) m->substream[0].mask = AV_CH_LAYOUT_STEREO; diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c index 1cb02f22a9..d8783b6f56 100644 --- a/libavcodec/mlpenc.c +++ b/libavcodec/mlpenc.c @@ -626,7 +626,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) ctx->ch_modifier_thd0 = 0; ctx->ch_modifier_thd1 = 0; ctx->ch_modifier_thd2 = 0; - ctx->channel_arrangement = 0; + ctx->channel_arrangement = 1; break; case AV_CH_LAYOUT_5POINT0_BACK: ctx->ch_modifier_thd0 = 1; From c8b5f2848dcdc7103a5b85c50c4c3082382d1f82 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Tue, 14 Dec 2021 16:35:14 -0800 Subject: [PATCH 533/894] avformat/aviobuf: ffio_copy_url_options Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/avio_internal.h | 6 ++++++ libavformat/aviobuf.c | 24 ++++++++++++++++++++++++ libavformat/dashdec.c | 27 +-------------------------- libavformat/hls.c | 24 +----------------------- 4 files changed, 32 insertions(+), 49 deletions(-) diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 187433f283..1f5e3d474b 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -206,6 +206,12 @@ int ffio_fdopen(AVIOContext **s, URLContext *h); */ URLContext *ffio_geturlcontext(AVIOContext *s); + +/** + * Read url related dictionary options from the AVIOContext and write to the given dictionary + */ +int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts); + /** * Open a write-only fake memory stream. The written data is not stored * anywhere - this is only used for measuring the amount of data diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 14d4b8f240..29d4bd7510 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -1020,6 +1020,30 @@ URLContext* ffio_geturlcontext(AVIOContext *s) return NULL; } +int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts) +{ + const char *opts[] = { + "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", NULL }; + const char **opt = opts; + uint8_t *buf = NULL; + int ret = 0; + + while (*opt) { + if (av_opt_get(pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { + if (buf[0] != '\0') { + ret = av_dict_set(avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); + if (ret < 0) + return ret; + } else { + av_freep(&buf); + } + } + opt++; + } + + return ret; +} + static void update_checksum(AVIOContext *s) { if (s->update_checksum && s->buf_ptr > s->checksum_ptr) { diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 983dc85d65..797fe74157 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -1833,31 +1833,6 @@ end: return ret; } -static int save_avio_options(AVFormatContext *s) -{ - DASHContext *c = s->priv_data; - const char *opts[] = { - "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", NULL }; - const char **opt = opts; - uint8_t *buf = NULL; - int ret = 0; - - while (*opt) { - if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { - if (buf[0] != '\0') { - ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) - return ret; - } else { - av_freep(&buf); - } - } - opt++; - } - - return ret; -} - static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **opts) { @@ -2057,7 +2032,7 @@ static int dash_read_header(AVFormatContext *s) c->interrupt_callback = &s->interrupt_callback; - if ((ret = save_avio_options(s)) < 0) + if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) return ret; if ((ret = parse_manifest(s, s->url, s->pb)) < 0) diff --git a/libavformat/hls.c b/libavformat/hls.c index 557faf8e8d..8c526f748f 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1717,28 +1717,6 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) return pls->start_seq_no; } -static int save_avio_options(AVFormatContext *s) -{ - HLSContext *c = s->priv_data; - static const char * const opts[] = { - "headers", "http_proxy", "user_agent", "cookies", "referer", "rw_timeout", "icy", NULL }; - const char * const * opt = opts; - uint8_t *buf; - int ret = 0; - - while (*opt) { - if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &buf) >= 0) { - ret = av_dict_set(&c->avio_opts, *opt, buf, - AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) - return ret; - } - opt++; - } - - return ret; -} - static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **opts) { @@ -1884,7 +1862,7 @@ static int hls_read_header(AVFormatContext *s) c->first_timestamp = AV_NOPTS_VALUE; c->cur_timestamp = AV_NOPTS_VALUE; - if ((ret = save_avio_options(s)) < 0) + if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) return ret; /* XXX: Some HLS servers don't like being sent the range header, From ad3c19dc9ef806c3ddbcc7b9c93d1ebaf14dd6e4 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Thu, 16 Dec 2021 11:35:39 -0800 Subject: [PATCH 534/894] avfilter/vf_yadif_cuda: simplify filter definition Signed-off-by: Aman Karmani Signed-off-by: Philip Langdale --- libavfilter/vf_yadif_cuda.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index da1ab5a8ff..685b8a2035 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -212,23 +212,6 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) s->input_frames = NULL; } -static int deint_cuda_query_formats(AVFilterContext *ctx) -{ - enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, - }; - int ret; - - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->inputs[0]->outcfg.formats)) < 0) - return ret; - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->outputs[0]->incfg.formats)) < 0) - return ret; - - return 0; -} - static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -380,9 +363,9 @@ const AVFilter ff_vf_yadif_cuda = { .priv_size = sizeof(DeintCUDAContext), .priv_class = &yadif_cuda_class, .uninit = deint_cuda_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), FILTER_INPUTS(deint_cuda_inputs), FILTER_OUTPUTS(deint_cuda_outputs), - FILTER_QUERY_FUNC(deint_cuda_query_formats), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; From c975946577f08cea35b2a94c0deecb4dd32a7e20 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Thu, 16 Dec 2021 11:28:01 -0800 Subject: [PATCH 535/894] build: detect Metal.framework and build .metal files Reviewed-by: Ridley Combs Signed-off-by: Aman Karmani --- .gitignore | 3 +++ configure | 12 +++++++++++- ffbuild/common.mak | 9 +++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9ed24b542e..1a5bb29ad5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ *.swp *.ver *.version +*.metal.air +*.metallib +*.metallib.c *.ptx *.ptx.c *.ptx.gz diff --git a/configure b/configure index 5fffcb8afe..32a39f5f5b 100755 --- a/configure +++ b/configure @@ -309,6 +309,7 @@ External library support: if openssl, gnutls or libtls is not used [no] --enable-mediacodec enable Android MediaCodec support [no] --enable-mediafoundation enable encoding via MediaFoundation [auto] + --disable-metal disable Apple Metal framework [autodetect] --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] --enable-openal enable OpenAL 1.1 capture support [no] --enable-opencl enable OpenCL processing [no] @@ -382,6 +383,8 @@ Toolchain options: --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] --nvcc=NVCC use Nvidia CUDA compiler NVCC or clang [$nvcc_default] --ld=LD use linker LD [$ld_default] + --metalcc=METALCC use metal compiler METALCC [$metalcc_default] + --metallib=METALLIB use metal linker METALLIB [$metallib_default] --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] --pkg-config-flags=FLAGS pass additional flags to pkgconf [] --ranlib=RANLIB use ranlib RANLIB [$ranlib_default] @@ -2564,6 +2567,8 @@ CMDLINE_SET=" ln_s logfile malloc_prefix + metalcc + metallib nm optflags nvcc @@ -3835,6 +3840,8 @@ host_cc_default="gcc" doxygen_default="doxygen" install="install" ln_s_default="ln -s -f" +metalcc_default="xcrun metal" +metallib_default="xcrun metallib" nm_default="nm -g" pkg_config_default=pkg-config ranlib_default="ranlib" @@ -4435,7 +4442,7 @@ if enabled cuda_nvcc; then fi set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ - target_exec x86asmexe + target_exec x86asmexe metalcc metallib enabled cross_compile || host_cc_default=$cc set_default host_cc @@ -6326,6 +6333,7 @@ check_apple_framework CoreFoundation check_apple_framework CoreMedia check_apple_framework CoreVideo check_apple_framework CoreAudio +check_apple_framework Metal enabled avfoundation && { disable coregraphics applicationservices @@ -7620,6 +7628,8 @@ ARFLAGS=$arflags AR_O=$ar_o AR_CMD=$ar NM_CMD=$nm +METALCC=$metalcc +METALLIB=$metallib RANLIB=$ranlib STRIP=$strip STRIPTYPE=$striptype diff --git a/ffbuild/common.mak b/ffbuild/common.mak index 0eb831d434..e79b509425 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -112,6 +112,15 @@ COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS) $(BIN2CEXE): ffbuild/bin2c_host.o $(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS) +%.metal.air: %.metal + $(METALCC) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ + +%.metallib: %.metal.air + $(METALLIB) --split-module-without-linking $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ + +%.metallib.c: %.metallib $(BIN2CEXE) + $(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@))) + %.ptx: %.cu $(SRC_PATH)/compat/cuda/cuda_runtime.h $(COMPILE_NVCC) From edca1fa17c4f4a87c9f563829dec526fced154a6 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Thu, 16 Dec 2021 12:03:00 -0800 Subject: [PATCH 536/894] avutil: add obj-c helpers into header-only include Reviewed-by: Ridley Combs Signed-off-by: Aman Karmani --- libavutil/objc.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 libavutil/objc.h diff --git a/libavutil/objc.h b/libavutil/objc.h new file mode 100644 index 0000000000..0db993f716 --- /dev/null +++ b/libavutil/objc.h @@ -0,0 +1,32 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OBJC_H +#define AVUTIL_OBJC_H + +#include + +static inline void ff_objc_release(NSObject **obj) +{ + if (*obj) { + [*obj release]; + *obj = nil; + } +} + +#endif /* AVUTIL_OBJC_H */ From ecee6af8bda475b15c9a4e9037fc406039f60efc Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Thu, 16 Dec 2021 12:04:07 -0800 Subject: [PATCH 537/894] avfilter: add metal utilities Reviewed-by: Ridley Combs Signed-off-by: Aman Karmani --- libavfilter/metal/utils.h | 35 +++++++++++++++++++ libavfilter/metal/utils.m | 73 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 libavfilter/metal/utils.h create mode 100644 libavfilter/metal/utils.m diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h new file mode 100644 index 0000000000..bd0319f63c --- /dev/null +++ b/libavfilter/metal/utils.h @@ -0,0 +1,35 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_METAL_UTILS_H +#define AVFILTER_METAL_UTILS_H + +#include +#include + +void ff_metal_compute_encoder_dispatch(id device, + id pipeline, + id encoder, + NSUInteger width, NSUInteger height); + +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, + CVMetalTextureCacheRef textureCache, + CVPixelBufferRef pixbuf, + int plane, + MTLPixelFormat format); +#endif /* AVFILTER_METAL_UTILS_H */ diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m new file mode 100644 index 0000000000..759ebedfba --- /dev/null +++ b/libavfilter/metal/utils.m @@ -0,0 +1,73 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/log.h" +#include + +void ff_metal_compute_encoder_dispatch(id device, + id pipeline, + id encoder, + NSUInteger width, NSUInteger height) +{ + [encoder setComputePipelineState:pipeline]; + NSUInteger w = pipeline.threadExecutionWidth; + NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; + MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); + BOOL fallback = YES; + if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { + if ([device supportsFamily:MTLGPUFamilyCommon3]) { + MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); + [encoder dispatchThreads:threadsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; + fallback = NO; + } + } + if (fallback) { + MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, + (height + h - 1) / h, + 1); + [encoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadsPerThreadgroup]; + } +} + +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *ctx, + CVMetalTextureCacheRef textureCache, + CVPixelBufferRef pixbuf, + int plane, + MTLPixelFormat format) +{ + CVMetalTextureRef tex = NULL; + CVReturn ret; + + ret = CVMetalTextureCacheCreateTextureFromImage( + NULL, + textureCache, + pixbuf, + NULL, + format, + CVPixelBufferGetWidthOfPlane(pixbuf, plane), + CVPixelBufferGetHeightOfPlane(pixbuf, plane), + plane, + &tex + ); + if (ret != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTexture from image: %d\n", ret); + return NULL; + } + + return tex; +} From 4ac869ca2a1caaa888ad65ebd9a9b1914bfaf9b8 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Mon, 13 Dec 2021 17:08:50 -0800 Subject: [PATCH 538/894] avfilter: add vf_yadif_videotoolbox deinterlaces CVPixelBuffers, i.e. AV_PIX_FMT_VIDEOTOOLBOX frames for example, an interlaced mpeg2 video can be decoded by avcodec, uploaded into a CVPixelBuffer, deinterlaced by Metal, and then encoded to h264 by VideoToolbox as follows: ffmpeg \ -init_hw_device videotoolbox \ -i interlaced.ts \ -vf hwupload,yadif_videotoolbox \ -c:v h264_videotoolbox \ -b:v 2000k \ -c:a copy \ -y progressive.ts (note that uploading AVFrame into CVPixelBuffer via hwupload requires 504c60660d3194758823ddd45ceddb86e35d806f) this work is sponsored by Fancy Bits LLC Reviewed-by: Ridley Combs Reviewed-by: Philip Langdale Signed-off-by: Aman Karmani --- Changelog | 1 + configure | 1 + libavfilter/Makefile | 4 + libavfilter/allfilters.c | 1 + libavfilter/metal/vf_yadif_videotoolbox.metal | 269 ++++++++++++ libavfilter/vf_yadif_videotoolbox.m | 406 ++++++++++++++++++ 6 files changed, 682 insertions(+) create mode 100644 libavfilter/metal/vf_yadif_videotoolbox.metal create mode 100644 libavfilter/vf_yadif_videotoolbox.m diff --git a/Changelog b/Changelog index 5c6adc0fa7..11f5d358c0 100644 --- a/Changelog +++ b/Changelog @@ -41,6 +41,7 @@ version : - libplacebo filter - vflip_vulkan, hflip_vulkan and flip_vulkan filters - adynamicequalizer audio filter +- yadif_videotoolbox filter version 4.4: diff --git a/configure b/configure index 32a39f5f5b..d8b07c8e00 100755 --- a/configure +++ b/configure @@ -3748,6 +3748,7 @@ vpp_qsv_filter_select="qsvvpp" xfade_opencl_filter_deps="opencl" yadif_cuda_filter_deps="ffnvcodec" yadif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" +yadif_videotoolbox_filter_deps="metal corevideo videotoolbox" # examples avio_list_dir_deps="avformat avutil" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 2fe495df28..9a061ba3c8 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -519,6 +519,10 @@ OBJS-$(CONFIG_XSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o yadif_common.o OBJS-$(CONFIG_YADIF_CUDA_FILTER) += vf_yadif_cuda.o vf_yadif_cuda.ptx.o \ yadif_common.o cuda/load_helper.o +OBJS-$(CONFIG_YADIF_VIDEOTOOLBOX_FILTER) += vf_yadif_videotoolbox.o \ + metal/vf_yadif_videotoolbox.metallib.o \ + metal/utils.o \ + yadif_common.o OBJS-$(CONFIG_YAEPBLUR_FILTER) += vf_yaepblur.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index ec57a2c49c..26f1c73505 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -496,6 +496,7 @@ extern const AVFilter ff_vf_xmedian; extern const AVFilter ff_vf_xstack; extern const AVFilter ff_vf_yadif; extern const AVFilter ff_vf_yadif_cuda; +extern const AVFilter ff_vf_yadif_videotoolbox; extern const AVFilter ff_vf_yaepblur; extern const AVFilter ff_vf_zmq; extern const AVFilter ff_vf_zoompan; diff --git a/libavfilter/metal/vf_yadif_videotoolbox.metal b/libavfilter/metal/vf_yadif_videotoolbox.metal new file mode 100644 index 0000000000..50783f2ffe --- /dev/null +++ b/libavfilter/metal/vf_yadif_videotoolbox.metal @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2018 Philip Langdale + * 2020 Aman Karmani + * 2020 Stefan Dyulgerov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +using namespace metal; + +/* + * Parameters + */ + +struct deintParams { + uint channels; + uint parity; + uint tff; + bool is_second_field; + bool skip_spatial_check; + int field_mode; +}; + +/* + * Texture access helpers + */ + +#define accesstype access::sample +const sampler s(coord::pixel); + +template +T tex2D(texture2d tex, uint x, uint y) +{ + return tex.sample(s, float2(x, y)).x; +} + +template <> +float2 tex2D(texture2d tex, uint x, uint y) +{ + return tex.sample(s, float2(x, y)).xy; +} + +template +T tex2D(texture2d tex, uint x, uint y) +{ + return tex.read(uint2(x, y)).x; +} + +template <> +float2 tex2D(texture2d tex, uint x, uint y) +{ + return tex.read(uint2(x, y)).xy; +} + +/* + * YADIF helpers + */ + +template +T spatial_predictor(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + T spatial_pred = (d + k)/2; + T spatial_score = abs(c - j) + abs(d - k) + abs(e - l); + + T score = abs(b - k) + abs(c - l) + abs(d - m); + if (score < spatial_score) { + spatial_pred = (c + l)/2; + spatial_score = score; + score = abs(a - l) + abs(b - m) + abs(c - n); + if (score < spatial_score) { + spatial_pred = (b + m)/2; + spatial_score = score; + } + } + score = abs(d - i) + abs(e - j) + abs(f - k); + if (score < spatial_score) { + spatial_pred = (e + j)/2; + spatial_score = score; + score = abs(e - h) + abs(f - i) + abs(g - j); + if (score < spatial_score) { + spatial_pred = (f + i)/2; + spatial_score = score; + } + } + return spatial_pred; +} + +template +T temporal_predictor(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + T p0 = (C + H) / 2; + T p1 = F; + T p2 = (D + I) / 2; + T p3 = G; + T p4 = (E + J) / 2; + + T tdiff0 = abs(D - I); + T tdiff1 = (abs(A - F) + abs(B - G)) / 2; + T tdiff2 = (abs(K - F) + abs(G - L)) / 2; + + T diff = max3(tdiff0, tdiff1, tdiff2); + + if (!skip_check) { + T maxi = max3(p2 - p3, p2 - p1, min(p0 - p1, p4 - p3)); + T mini = min3(p2 - p3, p2 - p1, max(p0 - p1, p4 - p3)); + diff = max3(diff, mini, -maxi); + } + + return clamp(spatial_pred, p2 - diff, p2 + diff); +} + +#define T float2 +template <> +T spatial_predictor(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + return T( + spatial_predictor(a.x, b.x, c.x, d.x, e.x, f.x, g.x, + h.x, i.x, j.x, k.x, l.x, m.x, n.x), + spatial_predictor(a.y, b.y, c.y, d.y, e.y, f.y, g.y, + h.y, i.y, j.y, k.y, l.y, m.y, n.y) + ); +} + +template <> +T temporal_predictor(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + return T( + temporal_predictor(A.x, B.x, C.x, D.x, E.x, F.x, + G.x, H.x, I.x, J.x, K.x, L.x, + spatial_pred.x, skip_check), + temporal_predictor(A.y, B.y, C.y, D.y, E.y, F.y, + G.y, H.y, I.y, J.y, K.y, L.y, + spatial_pred.y, skip_check) + ); +} +#undef T + +/* + * YADIF compute + */ + +template +T yadif_compute_spatial( + texture2d cur, + uint2 pos) +{ + // Calculate spatial prediction + T a = tex2D(cur, pos.x - 3, pos.y - 1); + T b = tex2D(cur, pos.x - 2, pos.y - 1); + T c = tex2D(cur, pos.x - 1, pos.y - 1); + T d = tex2D(cur, pos.x - 0, pos.y - 1); + T e = tex2D(cur, pos.x + 1, pos.y - 1); + T f = tex2D(cur, pos.x + 2, pos.y - 1); + T g = tex2D(cur, pos.x + 3, pos.y - 1); + + T h = tex2D(cur, pos.x - 3, pos.y + 1); + T i = tex2D(cur, pos.x - 2, pos.y + 1); + T j = tex2D(cur, pos.x - 1, pos.y + 1); + T k = tex2D(cur, pos.x - 0, pos.y + 1); + T l = tex2D(cur, pos.x + 1, pos.y + 1); + T m = tex2D(cur, pos.x + 2, pos.y + 1); + T n = tex2D(cur, pos.x + 3, pos.y + 1); + + return spatial_predictor(a, b, c, d, e, f, g, + h, i, j, k, l, m, n); +} + +template +T yadif_compute_temporal( + texture2d cur, + texture2d prev2, + texture2d prev1, + texture2d next1, + texture2d next2, + T spatial_pred, + bool skip_spatial_check, + uint2 pos) +{ + // Calculate temporal prediction + T A = tex2D(prev2, pos.x, pos.y - 1); + T B = tex2D(prev2, pos.x, pos.y + 1); + T C = tex2D(prev1, pos.x, pos.y - 2); + T D = tex2D(prev1, pos.x, pos.y + 0); + T E = tex2D(prev1, pos.x, pos.y + 2); + T F = tex2D(cur, pos.x, pos.y - 1); + T G = tex2D(cur, pos.x, pos.y + 1); + T H = tex2D(next1, pos.x, pos.y - 2); + T I = tex2D(next1, pos.x, pos.y + 0); + T J = tex2D(next1, pos.x, pos.y + 2); + T K = tex2D(next2, pos.x, pos.y - 1); + T L = tex2D(next2, pos.x, pos.y + 1); + + return temporal_predictor(A, B, C, D, E, F, G, H, I, J, K, L, + spatial_pred, skip_spatial_check); +} + +template +T yadif( + texture2d dst, + texture2d prev, + texture2d cur, + texture2d next, + constant deintParams& params, + uint2 pos) +{ + T spatial_pred = yadif_compute_spatial(cur, pos); + + if (params.is_second_field) { + return yadif_compute_temporal(cur, prev, cur, next, next, spatial_pred, params.skip_spatial_check, pos); + } else { + return yadif_compute_temporal(cur, prev, prev, cur, next, spatial_pred, params.skip_spatial_check, pos); + } +} + +/* + * Kernel dispatch + */ + +kernel void deint( + texture2d dst [[texture(0)]], + texture2d prev [[texture(1)]], + texture2d cur [[texture(2)]], + texture2d next [[texture(3)]], + constant deintParams& params [[buffer(4)]], + uint2 pos [[thread_position_in_grid]]) +{ + if ((pos.x >= dst.get_width()) || + (pos.y >= dst.get_height())) { + return; + } + + // Don't modify the primary field + if (pos.y % 2 == params.parity) { + float4 in = cur.read(pos); + dst.write(in, pos); + return; + } + + float2 pred; + if (params.channels == 1) + pred = float2(yadif(dst, prev, cur, next, params, pos)); + else + pred = yadif(dst, prev, cur, next, params, pos); + dst.write(pred.xyyy, pos); +} diff --git a/libavfilter/vf_yadif_videotoolbox.m b/libavfilter/vf_yadif_videotoolbox.m new file mode 100644 index 0000000000..af83a73e89 --- /dev/null +++ b/libavfilter/vf_yadif_videotoolbox.m @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2018 Philip Langdale + * 2020 Aman Karmani + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "internal.h" +#include "yadif.h" +#include +#include +#include +#include + +extern char ff_vf_yadif_videotoolbox_metallib_data[]; +extern unsigned int ff_vf_yadif_videotoolbox_metallib_len; + +typedef struct YADIFVTContext { + YADIFContext yadif; + + AVBufferRef *device_ref; + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + id mtlDevice; + id mtlLibrary; + id mtlQueue; + id mtlPipeline; + id mtlFunction; + id mtlParamsBuffer; + + CVMetalTextureCacheRef textureCache; +} YADIFVTContext; + +struct mtlYadifParams { + uint channels; + uint parity; + uint tff; + bool is_second_field; + bool skip_spatial_check; + int field_mode; +}; + +static void call_kernel(AVFilterContext *ctx, + id dst, + id prev, + id cur, + id next, + int channels, + int parity, + int tff) +{ + YADIFVTContext *s = ctx->priv; + id buffer = s->mtlQueue.commandBuffer; + id encoder = buffer.computeCommandEncoder; + struct mtlYadifParams *params = (struct mtlYadifParams *)s->mtlParamsBuffer.contents; + *params = (struct mtlYadifParams){ + .channels = channels, + .parity = parity, + .tff = tff, + .is_second_field = !(parity ^ tff), + .skip_spatial_check = s->yadif.mode&2, + .field_mode = s->yadif.current_field + }; + + [encoder setTexture:dst atIndex:0]; + [encoder setTexture:prev atIndex:1]; + [encoder setTexture:cur atIndex:2]; + [encoder setTexture:next atIndex:3]; + [encoder setBuffer:s->mtlParamsBuffer offset:0 atIndex:4]; + ff_metal_compute_encoder_dispatch(s->mtlDevice, s->mtlPipeline, encoder, dst.width, dst.height); + [encoder endEncoding]; + + [buffer commit]; + [buffer waitUntilCompleted]; + + ff_objc_release(&encoder); + ff_objc_release(&buffer); +} + +static void filter(AVFilterContext *ctx, AVFrame *dst, + int parity, int tff) +{ + YADIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int i; + + for (i = 0; i < y->csp->nb_components; i++) { + int pixel_size, channels; + const AVComponentDescriptor *comp = &y->csp->comp[i]; + CVMetalTextureRef prev, cur, next, dest; + id tex_prev, tex_cur, tex_next, tex_dest; + MTLPixelFormat format; + + if (comp->plane < i) { + // We process planes as a whole, so don't reprocess + // them for additional components + continue; + } + + pixel_size = (comp->depth + comp->shift) / 8; + channels = comp->step / pixel_size; + if (pixel_size > 2 || channels > 2) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + switch (pixel_size) { + case 1: + format = channels == 1 ? MTLPixelFormatR8Unorm : MTLPixelFormatRG8Unorm; + break; + case 2: + format = channels == 1 ? MTLPixelFormatR16Unorm : MTLPixelFormatRG16Unorm; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + av_log(ctx, AV_LOG_TRACE, + "Deinterlacing plane %d: pixel_size: %d channels: %d\n", + comp->plane, pixel_size, channels); + + prev = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->prev->data[3], i, format); + cur = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->cur->data[3], i, format); + next = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->next->data[3], i, format); + dest = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)dst->data[3], i, format); + + tex_prev = CVMetalTextureGetTexture(prev); + tex_cur = CVMetalTextureGetTexture(cur); + tex_next = CVMetalTextureGetTexture(next); + tex_dest = CVMetalTextureGetTexture(dest); + + call_kernel(ctx, tex_dest, tex_prev, tex_cur, tex_next, + channels, parity, tff); + + CFRelease(prev); + CFRelease(cur); + CFRelease(next); + CFRelease(dest); + } + + CVBufferPropagateAttachments((CVPixelBufferRef)y->cur->data[3], (CVPixelBufferRef)dst->data[3]); + + if (y->current_field == YADIF_FIELD_END) { + y->current_field = YADIF_FIELD_NORMAL; + } + +exit: + return; +} + +static av_cold void yadif_videotoolbox_uninit(AVFilterContext *ctx) +{ + YADIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + + av_frame_free(&y->prev); + av_frame_free(&y->cur); + av_frame_free(&y->next); + + av_buffer_unref(&s->device_ref); + av_buffer_unref(&s->input_frames_ref); + s->input_frames = NULL; + + ff_objc_release(&s->mtlParamsBuffer); + ff_objc_release(&s->mtlFunction); + ff_objc_release(&s->mtlPipeline); + ff_objc_release(&s->mtlQueue); + ff_objc_release(&s->mtlLibrary); + ff_objc_release(&s->mtlDevice); + + if (s->textureCache) { + CFRelease(s->textureCache); + s->textureCache = NULL; + } +} + +static av_cold int yadif_videotoolbox_init(AVFilterContext *ctx) +{ + YADIFVTContext *s = ctx->priv; + NSError *err = nil; + CVReturn ret; + + s->mtlDevice = MTLCreateSystemDefaultDevice(); + if (!s->mtlDevice) { + av_log(ctx, AV_LOG_ERROR, "Unable to find Metal device\n"); + goto fail; + } + + av_log(ctx, AV_LOG_INFO, "Using Metal device: %s\n", s->mtlDevice.name.UTF8String); + + dispatch_data_t libData = dispatch_data_create( + ff_vf_yadif_videotoolbox_metallib_data, + ff_vf_yadif_videotoolbox_metallib_len, + nil, + nil); + s->mtlLibrary = [s->mtlDevice newLibraryWithData:libData error:&err]; + dispatch_release(libData); + libData = nil; + if (err) { + av_log(ctx, AV_LOG_ERROR, "Failed to load Metal library: %s\n", err.description.UTF8String); + goto fail; + } + + s->mtlFunction = [s->mtlLibrary newFunctionWithName:@"deint"]; + if (!s->mtlFunction) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal function!\n"); + goto fail; + } + + s->mtlQueue = s->mtlDevice.newCommandQueue; + if (!s->mtlQueue) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal command queue!\n"); + goto fail; + } + + s->mtlPipeline = [s->mtlDevice + newComputePipelineStateWithFunction:s->mtlFunction + error:&err]; + if (err) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal compute pipeline: %s\n", err.description.UTF8String); + goto fail; + } + + s->mtlParamsBuffer = [s->mtlDevice + newBufferWithLength:sizeof(struct mtlYadifParams) + options:MTLResourceStorageModeShared]; + if (!s->mtlParamsBuffer) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal buffer for parameters\n"); + goto fail; + } + + ret = CVMetalTextureCacheCreate( + NULL, + NULL, + s->mtlDevice, + NULL, + &s->textureCache + ); + if (ret != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTextureCache: %d\n", ret); + goto fail; + } + + return 0; +fail: + yadif_videotoolbox_uninit(ctx); + return AVERROR_EXTERNAL; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + YADIFVTContext *s = ctx->priv; + + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + + s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); + if (!s->input_frames_ref) { + av_log(ctx, AV_LOG_ERROR, "A input frames reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + s->input_frames = (AVHWFramesContext*)s->input_frames_ref->data; + + return 0; +} + +static int config_output(AVFilterLink *link) +{ + AVHWFramesContext *output_frames; + AVFilterContext *ctx = link->src; + YADIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int ret = 0; + + av_assert0(s->input_frames); + s->device_ref = av_buffer_ref(s->input_frames->device_ref); + if (!s->device_ref) { + av_log(ctx, AV_LOG_ERROR, "A device reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + + link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); + if (!link->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + ret = AVERROR(ENOMEM); + goto exit; + } + + output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; + output_frames->sw_format = s->input_frames->sw_format; + output_frames->width = ctx->inputs[0]->w; + output_frames->height = ctx->inputs[0]->h; + + ret = ff_filter_init_hw_frames(ctx, link, 10); + if (ret < 0) + goto exit; + + ret = av_hwframe_ctx_init(link->hw_frames_ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VideoToolbox frame " + "context for output: %d\n", ret); + goto exit; + } + + link->time_base.num = ctx->inputs[0]->time_base.num; + link->time_base.den = ctx->inputs[0]->time_base.den * 2; + link->w = ctx->inputs[0]->w; + link->h = ctx->inputs[0]->h; + + if(y->mode & 1) + link->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + (AVRational){2, 1}); + + if (link->w < 3 || link->h < 3) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n"); + ret = AVERROR(EINVAL); + goto exit; + } + + y->csp = av_pix_fmt_desc_get(output_frames->sw_format); + y->filter = filter; + +exit: + return ret; +} + +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit } + +static const AVOption yadif_videotoolbox_options[] = { + #define OFFSET(x) offsetof(YADIFContext, x) + { "mode", "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 3, FLAGS, "mode"}, + CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME, "mode"), + CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD, "mode"), + CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"), + CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL, "mode"), + + { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=YADIF_PARITY_AUTO}, -1, 1, FLAGS, "parity" }, + CONST("tff", "assume top field first", YADIF_PARITY_TFF, "parity"), + CONST("bff", "assume bottom field first", YADIF_PARITY_BFF, "parity"), + CONST("auto", "auto detect parity", YADIF_PARITY_AUTO, "parity"), + + { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=YADIF_DEINT_ALL}, 0, 1, FLAGS, "deint" }, + CONST("all", "deinterlace all frames", YADIF_DEINT_ALL, "deint"), + CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED, "deint"), + #undef OFFSET + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(yadif_videotoolbox); + +static const AVFilterPad yadif_videotoolbox_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = ff_yadif_filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad yadif_videotoolbox_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = ff_yadif_request_frame, + .config_props = config_output, + }, +}; + +AVFilter ff_vf_yadif_videotoolbox = { + .name = "yadif_videotoolbox", + .description = NULL_IF_CONFIG_SMALL("YADIF for VideoToolbox frames using Metal compute"), + .priv_size = sizeof(YADIFVTContext), + .priv_class = &yadif_videotoolbox_class, + .init = yadif_videotoolbox_init, + .uninit = yadif_videotoolbox_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX), + FILTER_INPUTS(yadif_videotoolbox_inputs), + FILTER_OUTPUTS(yadif_videotoolbox_outputs), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 69a45b8a4998e61efd40b054e70abc722f7e155f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 20:12:34 +0100 Subject: [PATCH 539/894] avcodec/Makefile: Remove superfluous avformat->DNXHD dependencies There is no mxfenc dependency any more since commit b9a26b9d55f77ebbff3596e46be54bb5fed469d3. Also remove a dnxhddata.h inclusion in mxfenc that was forgotten in the very same commit. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 2 -- libavformat/mxfenc.c | 1 - 2 files changed, 3 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4122a9b144..fb90ecea84 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -983,14 +983,12 @@ OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddata.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o -OBJS-$(CONFIG_MXF_MUXER) += dnxhddata.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_SPDIF_MUXER) += dca.o diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index fcd9afda2a..00bbe58149 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -48,7 +48,6 @@ #include "libavutil/pixdesc.h" #include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" -#include "libavcodec/dnxhddata.h" #include "libavcodec/dv_profile.h" #include "libavcodec/h264_ps.h" #include "libavcodec/golomb.h" From c26730ed8fb7ca94ef448f53dd69da472aa4e75b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 15 Dec 2021 13:51:16 +0100 Subject: [PATCH 540/894] tests/dnn: Make DNN tests regular libavfilter tests They test libavfilter internal API, so they should be libavfilter test programs (which implies: linked statically to libavfilter to access internal APIs and linked normally (statically or dynamically depending upon the build configuration) against all the other libs). Right now, they are always linked statically against all libs, which is a significant size waste compared to shared libs as all of libavcodec has been pulled in despite not being really used. This also leads to linking failures on systems for which av_export_avutil is intended: libavcodec does not expect to be linked statically against the library providing avpriv_(cga|vga16)_font in this case. This is fixed by this commit. Signed-off-by: Andreas Rheinhardt --- libavfilter/Makefile | 3 ++ libavfilter/tests/.gitignore | 8 +++++ .../tests/dnn-layer-avgpool.c | 0 .../tests/dnn-layer-conv2d.c | 0 .../tests/dnn-layer-dense.c | 0 .../tests/dnn-layer-depth2space.c | 0 .../tests/dnn-layer-mathbinary.c | 0 .../tests/dnn-layer-mathunary.c | 0 .../tests/dnn-layer-maximum.c | 0 .../tests/dnn-layer-pad.c | 0 tests/Makefile | 5 ++- tests/dnn/.gitignore | 8 ----- tests/dnn/Makefile | 18 ---------- tests/fate/dnn.mak | 34 ++++++++++--------- 14 files changed, 31 insertions(+), 45 deletions(-) rename tests/dnn/dnn-layer-avgpool-test.c => libavfilter/tests/dnn-layer-avgpool.c (100%) rename tests/dnn/dnn-layer-conv2d-test.c => libavfilter/tests/dnn-layer-conv2d.c (100%) rename tests/dnn/dnn-layer-dense-test.c => libavfilter/tests/dnn-layer-dense.c (100%) rename tests/dnn/dnn-layer-depth2space-test.c => libavfilter/tests/dnn-layer-depth2space.c (100%) rename tests/dnn/dnn-layer-mathbinary-test.c => libavfilter/tests/dnn-layer-mathbinary.c (100%) rename tests/dnn/dnn-layer-mathunary-test.c => libavfilter/tests/dnn-layer-mathunary.c (100%) rename tests/dnn/dnn-layer-maximum-test.c => libavfilter/tests/dnn-layer-maximum.c (100%) rename tests/dnn/dnn-layer-pad-test.c => libavfilter/tests/dnn-layer-pad.c (100%) delete mode 100644 tests/dnn/.gitignore delete mode 100644 tests/dnn/Makefile diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 9a061ba3c8..cb328c2bf8 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -590,6 +590,9 @@ SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral +TESTPROGS-$(CONFIG_DNN) += dnn-layer-avgpool dnn-layer-conv2d dnn-layer-dense \ + dnn-layer-depth2space dnn-layer-mathbinary \ + dnn-layer-mathunary dnn-layer-maximum dnn-layer-pad \ TOOLS-$(CONFIG_LIBZMQ) += zmqsend diff --git a/libavfilter/tests/.gitignore b/libavfilter/tests/.gitignore index 65ef86f2e5..db482cd49b 100644 --- a/libavfilter/tests/.gitignore +++ b/libavfilter/tests/.gitignore @@ -1,3 +1,11 @@ +/dnn-layer-conv2d +/dnn-layer-depth2space +/dnn-layer-maximum +/dnn-layer-pad +/dnn-layer-mathbinary +/dnn-layer-mathunary +/dnn-layer-avgpool +/dnn-layer-dense /drawutils /filtfmts /formats diff --git a/tests/dnn/dnn-layer-avgpool-test.c b/libavfilter/tests/dnn-layer-avgpool.c similarity index 100% rename from tests/dnn/dnn-layer-avgpool-test.c rename to libavfilter/tests/dnn-layer-avgpool.c diff --git a/tests/dnn/dnn-layer-conv2d-test.c b/libavfilter/tests/dnn-layer-conv2d.c similarity index 100% rename from tests/dnn/dnn-layer-conv2d-test.c rename to libavfilter/tests/dnn-layer-conv2d.c diff --git a/tests/dnn/dnn-layer-dense-test.c b/libavfilter/tests/dnn-layer-dense.c similarity index 100% rename from tests/dnn/dnn-layer-dense-test.c rename to libavfilter/tests/dnn-layer-dense.c diff --git a/tests/dnn/dnn-layer-depth2space-test.c b/libavfilter/tests/dnn-layer-depth2space.c similarity index 100% rename from tests/dnn/dnn-layer-depth2space-test.c rename to libavfilter/tests/dnn-layer-depth2space.c diff --git a/tests/dnn/dnn-layer-mathbinary-test.c b/libavfilter/tests/dnn-layer-mathbinary.c similarity index 100% rename from tests/dnn/dnn-layer-mathbinary-test.c rename to libavfilter/tests/dnn-layer-mathbinary.c diff --git a/tests/dnn/dnn-layer-mathunary-test.c b/libavfilter/tests/dnn-layer-mathunary.c similarity index 100% rename from tests/dnn/dnn-layer-mathunary-test.c rename to libavfilter/tests/dnn-layer-mathunary.c diff --git a/tests/dnn/dnn-layer-maximum-test.c b/libavfilter/tests/dnn-layer-maximum.c similarity index 100% rename from tests/dnn/dnn-layer-maximum-test.c rename to libavfilter/tests/dnn-layer-maximum.c diff --git a/tests/dnn/dnn-layer-pad-test.c b/libavfilter/tests/dnn-layer-pad.c similarity index 100% rename from tests/dnn/dnn-layer-pad-test.c rename to libavfilter/tests/dnn-layer-pad.c diff --git a/tests/Makefile b/tests/Makefile index 1e0345b163..1bf9a7a36b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,3 +1,4 @@ + THREADS = 1 VREF = tests/vsynth1/00.pgm AREF = tests/data/asynth1.sw @@ -10,8 +11,7 @@ FFMPEG=ffmpeg$(PROGSSUF)$(EXESUF) $(AREF): CMP= APITESTSDIR := tests/api -DNNTESTSDIR := tests/dnn -FATE_OUTDIRS = tests/data tests/data/fate tests/data/filtergraphs tests/data/lavf tests/data/lavf-fate tests/data/pixfmt tests/vsynth1 $(APITESTSDIR) $(DNNTESTSDIR) +FATE_OUTDIRS = tests/data tests/data/fate tests/data/filtergraphs tests/data/lavf tests/data/lavf-fate tests/data/pixfmt tests/vsynth1 $(APITESTSDIR) OUTDIRS += $(FATE_OUTDIRS) $(VREF): tests/videogen$(HOSTEXESUF) | tests/vsynth1 @@ -96,7 +96,6 @@ CONFIG_LARGE_TESTS:= endif include $(SRC_PATH)/$(APITESTSDIR)/Makefile -include $(SRC_PATH)/$(DNNTESTSDIR)/Makefile include $(SRC_PATH)/tests/fate/acodec.mak include $(SRC_PATH)/tests/fate/vcodec.mak diff --git a/tests/dnn/.gitignore b/tests/dnn/.gitignore deleted file mode 100644 index 03b04d6653..0000000000 --- a/tests/dnn/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/dnn-layer-conv2d-test -/dnn-layer-depth2space-test -/dnn-layer-maximum-test -/dnn-layer-pad-test -/dnn-layer-mathbinary-test -/dnn-layer-mathunary-test -/dnn-layer-avgpool-test -/dnn-layer-dense-test diff --git a/tests/dnn/Makefile b/tests/dnn/Makefile deleted file mode 100644 index ef827520de..0000000000 --- a/tests/dnn/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -DNNTESTPROGS += dnn-layer-pad -DNNTESTPROGS += dnn-layer-conv2d -DNNTESTPROGS += dnn-layer-depth2space -DNNTESTPROGS += dnn-layer-dense -DNNTESTPROGS += dnn-layer-mathbinary -DNNTESTPROGS += dnn-layer-maximum -DNNTESTPROGS += dnn-layer-mathunary -DNNTESTPROGS += dnn-layer-avgpool - -DNNTESTOBJS := $(DNNTESTOBJS:%=$(DNNTESTSDIR)%) $(DNNTESTPROGS:%=$(DNNTESTSDIR)/%-test.o) -DNNTESTPROGS := $(DNNTESTPROGS:%=$(DNNTESTSDIR)/%-test$(EXESUF)) --include $(wildcard $(DNNTESTOBJS:.o=.d)) - -$(DNNTESTPROGS): %$(EXESUF): %.o $(FF_STATIC_DEP_LIBS) - $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter %.o,$^) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS-avcodec) $(EXTRALIBS-avfilter) $(EXTRALIBS-avformat) $(EXTRALIBS-avutil) $(EXTRALIBS-swresample) $(EXTRALIBS) - -testclean:: - $(RM) $(addprefix $(DNNTESTSDIR)/,$(CLEANSUFFIXES) *-test$(EXESUF)) diff --git a/tests/fate/dnn.mak b/tests/fate/dnn.mak index ef07ee45f8..a30a2976d9 100644 --- a/tests/fate/dnn.mak +++ b/tests/fate/dnn.mak @@ -1,41 +1,43 @@ +DNNTESTSDIR := libavfilter/tests + FATE_DNN += fate-dnn-layer-pad -fate-dnn-layer-pad: $(DNNTESTSDIR)/dnn-layer-pad-test$(EXESUF) -fate-dnn-layer-pad: CMD = run $(DNNTESTSDIR)/dnn-layer-pad-test$(EXESUF) +fate-dnn-layer-pad: $(DNNTESTSDIR)/dnn-layer-pad$(EXESUF) +fate-dnn-layer-pad: CMD = run $(DNNTESTSDIR)/dnn-layer-pad$(EXESUF) fate-dnn-layer-pad: CMP = null FATE_DNN += fate-dnn-layer-conv2d -fate-dnn-layer-conv2d: $(DNNTESTSDIR)/dnn-layer-conv2d-test$(EXESUF) -fate-dnn-layer-conv2d: CMD = run $(DNNTESTSDIR)/dnn-layer-conv2d-test$(EXESUF) +fate-dnn-layer-conv2d: $(DNNTESTSDIR)/dnn-layer-conv2d$(EXESUF) +fate-dnn-layer-conv2d: CMD = run $(DNNTESTSDIR)/dnn-layer-conv2d$(EXESUF) fate-dnn-layer-conv2d: CMP = null FATE_DNN += fate-dnn-layer-dense -fate-dnn-layer-dense: $(DNNTESTSDIR)/dnn-layer-dense-test$(EXESUF) -fate-dnn-layer-dense: CMD = run $(DNNTESTSDIR)/dnn-layer-dense-test$(EXESUF) +fate-dnn-layer-dense: $(DNNTESTSDIR)/dnn-layer-dense$(EXESUF) +fate-dnn-layer-dense: CMD = run $(DNNTESTSDIR)/dnn-layer-dense$(EXESUF) fate-dnn-layer-dense: CMP = null FATE_DNN += fate-dnn-layer-depth2space -fate-dnn-layer-depth2space: $(DNNTESTSDIR)/dnn-layer-depth2space-test$(EXESUF) -fate-dnn-layer-depth2space: CMD = run $(DNNTESTSDIR)/dnn-layer-depth2space-test$(EXESUF) +fate-dnn-layer-depth2space: $(DNNTESTSDIR)/dnn-layer-depth2space$(EXESUF) +fate-dnn-layer-depth2space: CMD = run $(DNNTESTSDIR)/dnn-layer-depth2space$(EXESUF) fate-dnn-layer-depth2space: CMP = null FATE_DNN += fate-dnn-layer-mathbinary -fate-dnn-layer-mathbinary: $(DNNTESTSDIR)/dnn-layer-mathbinary-test$(EXESUF) -fate-dnn-layer-mathbinary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathbinary-test$(EXESUF) +fate-dnn-layer-mathbinary: $(DNNTESTSDIR)/dnn-layer-mathbinary$(EXESUF) +fate-dnn-layer-mathbinary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathbinary$(EXESUF) fate-dnn-layer-mathbinary: CMP = null FATE_DNN += fate-dnn-layer-maximum -fate-dnn-layer-maximum: $(DNNTESTSDIR)/dnn-layer-maximum-test$(EXESUF) -fate-dnn-layer-maximum: CMD = run $(DNNTESTSDIR)/dnn-layer-maximum-test$(EXESUF) +fate-dnn-layer-maximum: $(DNNTESTSDIR)/dnn-layer-maximum$(EXESUF) +fate-dnn-layer-maximum: CMD = run $(DNNTESTSDIR)/dnn-layer-maximum$(EXESUF) fate-dnn-layer-maximum: CMP = null FATE_DNN += fate-dnn-layer-mathunary -fate-dnn-layer-mathunary: $(DNNTESTSDIR)/dnn-layer-mathunary-test$(EXESUF) -fate-dnn-layer-mathunary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathunary-test$(EXESUF) +fate-dnn-layer-mathunary: $(DNNTESTSDIR)/dnn-layer-mathunary$(EXESUF) +fate-dnn-layer-mathunary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathunary$(EXESUF) fate-dnn-layer-mathunary: CMP = null FATE_DNN += fate-dnn-layer-avgpool -fate-dnn-layer-avgpool: $(DNNTESTSDIR)/dnn-layer-avgpool-test$(EXESUF) -fate-dnn-layer-avgpool: CMD = run $(DNNTESTSDIR)/dnn-layer-avgpool-test$(EXESUF) +fate-dnn-layer-avgpool: $(DNNTESTSDIR)/dnn-layer-avgpool$(EXESUF) +fate-dnn-layer-avgpool: CMD = run $(DNNTESTSDIR)/dnn-layer-avgpool$(EXESUF) fate-dnn-layer-avgpool: CMP = null FATE-$(CONFIG_DNN) += $(FATE_DNN) From 25ddf888d8bac2a9c55a18f9651f27a62d50e2fb Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 20:20:18 +0100 Subject: [PATCH 541/894] avformat/mxfenc: Use smaller types to make struct smaller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mxfenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 00bbe58149..bb6d94bda5 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -2195,9 +2195,9 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) static const struct { UID uid; int frame_size; - int profile; + uint8_t profile; uint8_t interlaced; - int intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored + int8_t intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored } mxf_h264_codec_uls[] = { {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 0, 66, 0, -1 }, // AVC Baseline {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x20,0x01 }, 0, 77, 0, -1 }, // AVC Main From bb69b734c74cc22301a4fa2c3263077ffe7064b1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 7 Nov 2021 22:11:22 +0100 Subject: [PATCH 542/894] avformat/mxfenc: Avoid allocation for timecode track MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mxfenc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index bb6d94bda5..1cdfc07382 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -420,6 +420,7 @@ typedef struct MXFContext { int track_instance_count; // used to generate MXFTrack uuids int cbr_index; ///< use a constant bitrate index uint8_t unused_tags[MXF_NUM_TAGS]; ///< local tags that we know will not be used + MXFStreamContext timecode_track_priv; } MXFContext; static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value) @@ -2704,9 +2705,7 @@ static int mxf_init(AVFormatContext *s) mxf->timecode_track = av_mallocz(sizeof(*mxf->timecode_track)); if (!mxf->timecode_track) return AVERROR(ENOMEM); - mxf->timecode_track->priv_data = av_mallocz(sizeof(MXFStreamContext)); - if (!mxf->timecode_track->priv_data) - return AVERROR(ENOMEM); + mxf->timecode_track->priv_data = &mxf->timecode_track_priv; mxf->timecode_track->index = -1; return 0; @@ -3079,10 +3078,7 @@ static void mxf_deinit(AVFormatContext *s) av_freep(&mxf->index_entries); av_freep(&mxf->body_partition_offset); - if (mxf->timecode_track) { - av_freep(&mxf->timecode_track->priv_data); - av_freep(&mxf->timecode_track); - } + av_freep(&mxf->timecode_track); } static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flush) From dfd06ee710b547e0027a38f63cabe868e9ef1a3c Mon Sep 17 00:00:00 2001 From: Sebastian Kirmayer Date: Mon, 9 Aug 2021 03:26:20 +0200 Subject: [PATCH 543/894] avutil/twofish: Fixed decryption The previous implementation swapped the two halves of the plaintext. The existing tests only decrypted data with a plaintext of all zeroes, which is not affected by swapping the halves. Tests which detect the old buggy behavior have been added. Signed-off-by: Sebastian Kirmayer Signed-off-by: Andreas Rheinhardt --- libavutil/tests/twofish.c | 15 ++++++++++++--- libavutil/twofish.c | 8 ++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/libavutil/tests/twofish.c b/libavutil/tests/twofish.c index 74e0926eaf..7e8b129230 100644 --- a/libavutil/tests/twofish.c +++ b/libavutil/tests/twofish.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) }; uint8_t temp[32], iv[16], rpt[32] = {0}; const int kbits[3] = {128, 192, 256}; - int i, j, err = 0; + int i, j, k, err = 0; struct AVTWOFISH *cs; cs = av_twofish_alloc(); if (!cs) @@ -70,10 +70,19 @@ int main(int argc, char *argv[]) memcpy(Key+16,Key,(kbits[j]-128) >> 3); memcpy(Key,rpt,16); memcpy(rpt,temp,16); + av_twofish_crypt(cs, temp, temp, 1, NULL, 1); + for (k = 0; k < 16; k++) { + // Need to compare to Key here, because the plaintext comes + // from rpt but was moved over to Key. + if (Key[k] != temp[k]) { + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", k, Key[k], temp[k]); + err = 1; + } + } } for (i = 0; i < 16; i++) { - if (rct[3 + j][i] != temp[i]) { - av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[3 + j][i], temp[i]); + if (rct[3 + j][i] != rpt[i]) { + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[3 + j][i], rpt[i]); err = 1; } } diff --git a/libavutil/twofish.c b/libavutil/twofish.c index d84fa4f363..649b4bc41b 100644 --- a/libavutil/twofish.c +++ b/libavutil/twofish.c @@ -260,10 +260,10 @@ static void twofish_decrypt(AVTWOFISH *cs, uint8_t *dst, const uint8_t *src, uin P[3] ^= AV_RL32(iv + 12); memcpy(iv, src, 16); } - AV_WL32(dst, P[2]); - AV_WL32(dst + 4, P[3]); - AV_WL32(dst + 8, P[0]); - AV_WL32(dst + 12, P[1]); + AV_WL32(dst, P[0]); + AV_WL32(dst + 4, P[1]); + AV_WL32(dst + 8, P[2]); + AV_WL32(dst + 12, P[3]); } av_cold int av_twofish_init(AVTWOFISH *cs, const uint8_t *key, int key_bits) From 17605d1a4afa5761271b27b2aea756a772ca0efc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 21 Apr 2021 06:24:04 +0200 Subject: [PATCH 544/894] avcodec/ffv1dec: Remove redundant writes, fix races Every modification of the data that is copied in update_thread_context() is a data race if it happens after ff_thread_finish_setup. ffv1dec's update_thread_context() simply uses memcpy for updating the new context, so that every modification of the src's context is a race. Some of these modifications are unnecessary: picture_number is write-only for the decoder and cur will be reset when decoding the next frame anyway. So remove them. And while just at it, also don't set cur for the slice contexts as this variable is write-only. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavcodec/ffv1dec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 374546f4b3..74c907a156 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -924,7 +924,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac fs->c.bytestream_end = buf_p + v; fs->avctx = avctx; - fs->cur = p; } avctx->execute(avctx, @@ -965,11 +964,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac } ff_thread_report_progress(&f->picture, INT_MAX, 0); - f->picture_number++; - if (f->last_picture.f) ff_thread_release_buffer(avctx, &f->last_picture); - f->cur = NULL; if ((ret = av_frame_ref(data, f->picture.f)) < 0) return ret; From 485121b92ce7a7447428c53ba875c58c79dc9e6a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 21 Apr 2021 10:12:15 +0200 Subject: [PATCH 545/894] avcodec/ffv1, ffv1dec: Add const where appropriate Signed-off-by: Andreas Rheinhardt --- libavcodec/ffv1.c | 4 ++-- libavcodec/ffv1.h | 4 ++-- libavcodec/ffv1dec.c | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index a27eca5ae3..d8a0c39254 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -63,7 +63,7 @@ av_cold int ff_ffv1_common_init(AVCodecContext *avctx) return 0; } -av_cold int ff_ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) +av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs) { int j, i; @@ -170,7 +170,7 @@ int ff_ffv1_allocate_initial_states(FFV1Context *f) return 0; } -void ff_ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs) +void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs) { int i, j; diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 473780c876..8ffe5ab433 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -139,11 +139,11 @@ typedef struct FFV1Context { } FFV1Context; int ff_ffv1_common_init(AVCodecContext *avctx); -int ff_ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs); +int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs); int ff_ffv1_init_slices_state(FFV1Context *f); int ff_ffv1_init_slice_contexts(FFV1Context *f); int ff_ffv1_allocate_initial_states(FFV1Context *f); -void ff_ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs); +void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs); int ff_ffv1_close(AVCodecContext *avctx); static av_always_inline int fold(int diff, int bits) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 74c907a156..c6af4e9bc0 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -161,7 +161,7 @@ static int decode_plane(FFV1Context *s, uint8_t *src, return 0; } -static int decode_slice_header(FFV1Context *f, FFV1Context *fs) +static int decode_slice_header(const FFV1Context *f, FFV1Context *fs) { RangeCoder *c = &fs->c; uint8_t state[CONTEXT_SIZE]; @@ -974,7 +974,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac return buf_size; } -static void copy_fields(FFV1Context *fsdst, FFV1Context *fssrc, FFV1Context *fsrc) +static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc, + const FFV1Context *fsrc) { fsdst->version = fsrc->version; fsdst->micro_version = fsrc->micro_version; From 98f87c3d2920c14985de5ac8b7c698a20b03468f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 21 Apr 2021 12:31:14 +0200 Subject: [PATCH 546/894] avcodec/ffv1dec: Don't copy unused field The decoder always uses AVCodecContext.bits_per_raw_sample. Signed-off-by: Andreas Rheinhardt --- libavcodec/ffv1dec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index c6af4e9bc0..810b2e18f0 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -992,7 +992,6 @@ static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc, fsdst->slice_damaged = fssrc->slice_damaged; fsdst->key_frame_ok = fsrc->key_frame_ok; - fsdst->bits_per_raw_sample = fsrc->bits_per_raw_sample; fsdst->packed_at_lsb = fsrc->packed_at_lsb; fsdst->slice_count = fsrc->slice_count; if (fsrc->version<3){ From 3857ecbe70e81cb6ad7a7f155c311e8522b93b3e Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 13 Dec 2021 14:50:34 +0800 Subject: [PATCH 547/894] lavc/qsvenc: remove VC1 profiles The SDK doesn't support VC1 encoding. In addition, both MFX_PROFILE_VC1_SIMPLE and MFX_PROFILE_HEVC_MAIN are 1 in the SDK, HEVC main profile is recognized as simple profile in the verbose output if don't remove VC1 profiles. $ ffmpeg -v verbose -qsv_device /dev/dri/renderD129 -f lavfi -i yuvtestsrc -c:v hevc_qsv -f null - [hevc_qsv @ 0x55bdf7eb4eb0] profile: simple; level: 21 Signed-off-by: Zhong Li --- libavcodec/qsvenc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 26a94cd419..dc0c45dc45 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -60,9 +60,6 @@ static const struct { { MFX_PROFILE_MPEG2_SIMPLE, "simple" }, { MFX_PROFILE_MPEG2_MAIN, "main" }, { MFX_PROFILE_MPEG2_HIGH, "high" }, - { MFX_PROFILE_VC1_SIMPLE, "simple" }, - { MFX_PROFILE_VC1_MAIN, "main" }, - { MFX_PROFILE_VC1_ADVANCED, "advanced" }, #if QSV_VERSION_ATLEAST(1, 8) { MFX_PROFILE_HEVC_MAIN, "main" }, { MFX_PROFILE_HEVC_MAIN10, "main10" }, From 50c38e1a4453f8073b980e91b336e7d94e65769a Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 13 Dec 2021 14:50:35 +0800 Subject: [PATCH 548/894] lavc/qsvenc: define profile array per codec The SDK defines HEVC, VP9 and AV1 profiles in the same values e.g. MFX_PROFILE_HEVC_MAIN =1, MFX_PROFILE_VP9_0 =1, MFX_PROFILE_AV1_MAIN =1, To avoid potential errors when adding VP9, AV1 profiles later, this patch defines profile array per codec. Signed-off-by: Zhong Li --- libavcodec/qsvenc.c | 47 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index dc0c45dc45..7dab8bab0f 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -41,10 +41,12 @@ #include "qsv_internal.h" #include "qsvenc.h" -static const struct { +struct profile_names { mfxU16 profile; const char *name; -} profile_names[] = { +}; + +static const struct profile_names avc_profiles[] = { { MFX_PROFILE_AVC_BASELINE, "baseline" }, { MFX_PROFILE_AVC_MAIN, "main" }, { MFX_PROFILE_AVC_EXTENDED, "extended" }, @@ -57,9 +59,15 @@ static const struct { { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "constrained high" }, { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "progressive high" }, #endif +}; + +static const struct profile_names mpeg2_profiles[] = { { MFX_PROFILE_MPEG2_SIMPLE, "simple" }, { MFX_PROFILE_MPEG2_MAIN, "main" }, { MFX_PROFILE_MPEG2_HIGH, "high" }, +}; + +static const struct profile_names hevc_profiles[] = { #if QSV_VERSION_ATLEAST(1, 8) { MFX_PROFILE_HEVC_MAIN, "main" }, { MFX_PROFILE_HEVC_MAIN10, "main10" }, @@ -68,12 +76,35 @@ static const struct { #endif }; -static const char *print_profile(mfxU16 profile) +static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) { - int i; - for (i = 0; i < FF_ARRAY_ELEMS(profile_names); i++) - if (profile == profile_names[i].profile) - return profile_names[i].name; + const struct profile_names *profiles; + int i, num_profiles; + + switch (codec_id) { + case AV_CODEC_ID_H264: + profiles = avc_profiles; + num_profiles = FF_ARRAY_ELEMS(avc_profiles); + break; + + case AV_CODEC_ID_MPEG2VIDEO: + profiles = mpeg2_profiles; + num_profiles = FF_ARRAY_ELEMS(mpeg2_profiles); + break; + + case AV_CODEC_ID_HEVC: + profiles = hevc_profiles; + num_profiles = FF_ARRAY_ELEMS(hevc_profiles); + break; + + default: + return "unknown"; + } + + for (i = 0; i < num_profiles; i++) + if (profile == profiles[i].profile) + return profiles[i].name; + return "unknown"; } @@ -143,7 +174,7 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, #endif av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", - print_profile(info->CodecProfile), info->CodecLevel); + print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", info->GopPicSize, info->GopRefDist); From 2544f709ba8ae2b4929183ddf37f3e3acc6cac5a Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 13 Dec 2021 14:50:36 +0800 Subject: [PATCH 549/894] lavc/qsvenc: add VP9 profiles Signed-off-by: Zhong Li --- libavcodec/qsvenc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 7dab8bab0f..a2a8a79189 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -76,6 +76,15 @@ static const struct profile_names hevc_profiles[] = { #endif }; +static const struct profile_names vp9_profiles[] = { +#if QSV_VERSION_ATLEAST(1, 19) + { MFX_PROFILE_VP9_0, "0" }, + { MFX_PROFILE_VP9_1, "1" }, + { MFX_PROFILE_VP9_2, "2" }, + { MFX_PROFILE_VP9_3, "3" }, +#endif +}; + static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) { const struct profile_names *profiles; @@ -97,6 +106,11 @@ static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) num_profiles = FF_ARRAY_ELEMS(hevc_profiles); break; + case AV_CODEC_ID_VP9: + profiles = vp9_profiles; + num_profiles = FF_ARRAY_ELEMS(vp9_profiles); + break; + default: return "unknown"; } From 45801af11f29c2448db0b89f81b904b568bcd7dc Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 13 Dec 2021 14:50:37 +0800 Subject: [PATCH 550/894] lavc/qsvenc: dump parameters for VP9 encoding in verbose mode Signed-off-by: Zhong Li --- libavcodec/qsvenc.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index a2a8a79189..106438f227 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -343,6 +343,84 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, } +static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, + mfxExtBuffer **coding_opts) +{ + mfxInfoMFX *info = &q->param.mfx; +#if QSV_HAVE_EXT_VP9_PARAM + mfxExtVP9Param *vp9_param = (mfxExtVP9Param *)coding_opts[0]; +#endif +#if QSV_HAVE_CO2 + mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1]; +#endif + + av_log(avctx, AV_LOG_VERBOSE, "profile: %s \n", + print_profile(avctx->codec_id, info->CodecProfile)); + + av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", + info->GopPicSize, info->GopRefDist); + if (info->GopOptFlag & MFX_GOP_CLOSED) + av_log(avctx, AV_LOG_VERBOSE, "closed "); + if (info->GopOptFlag & MFX_GOP_STRICT) + av_log(avctx, AV_LOG_VERBOSE, "strict "); + av_log(avctx, AV_LOG_VERBOSE, "; IdrInterval: %"PRIu16"\n", info->IdrInterval); + + av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n", + info->TargetUsage, print_ratecontrol(info->RateControlMethod)); + + if (info->RateControlMethod == MFX_RATECONTROL_CBR || + info->RateControlMethod == MFX_RATECONTROL_VBR) { + av_log(avctx, AV_LOG_VERBOSE, + "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", + info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier); + } else if (info->RateControlMethod == MFX_RATECONTROL_CQP) { + av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", + info->QPI, info->QPP, info->QPB); + } +#if QSV_HAVE_ICQ + else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) { + av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality); + } +#endif + else { + av_log(avctx, AV_LOG_VERBOSE, "Unsupported ratecontrol method: %d \n", info->RateControlMethod); + } + + av_log(avctx, AV_LOG_VERBOSE, "NumRefFrame: %"PRIu16"\n", info->NumRefFrame); + +#if QSV_HAVE_CO2 + av_log(avctx, AV_LOG_VERBOSE, + "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", + co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); + + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, + "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", + print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), + print_threestate(co2->ExtBRC)); + +#if QSV_HAVE_VDENC + av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower)); +#endif + +#if QSV_VERSION_ATLEAST(1, 9) + av_log(avctx, AV_LOG_VERBOSE, + "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", + co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); +#endif +#endif + + av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", + info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); + +#if QSV_HAVE_EXT_VP9_PARAM + av_log(avctx, AV_LOG_VERBOSE, "WriteIVFHeaders: %s \n", + print_threestate(vp9_param->WriteIVFHeaders)); +#endif +} + static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) { const char *rc_desc; @@ -941,6 +1019,8 @@ static int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q) q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000; + dump_video_vp9_param(avctx, q, ext_buffers); + return 0; } From bbe9faa01cb1a60ddcfb35c79907bdba4bf24a5c Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 13 Dec 2021 14:50:38 +0800 Subject: [PATCH 551/894] lavc/qsvenc: dump parameters for mjpeg encoding in verbose mode Signed-off-by: Zhong Li --- libavcodec/qsvenc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 106438f227..92a8b49fe3 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -421,6 +421,18 @@ static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, #endif } +static void dump_video_mjpeg_param(AVCodecContext *avctx, QSVEncContext *q) +{ + mfxInfoMFX *info = &q->param.mfx; + + av_log(avctx, AV_LOG_VERBOSE, "Interleaved: %"PRIu16" \n", info->Interleaved); + av_log(avctx, AV_LOG_VERBOSE, "Quality: %"PRIu16" \n", info->Quality); + av_log(avctx, AV_LOG_VERBOSE, "RestartInterval: %"PRIu16" \n", info->RestartInterval); + + av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", + info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); +} + static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) { const char *rc_desc; @@ -970,6 +982,8 @@ static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) if (q->packet_size == 0) q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4; + dump_video_mjpeg_param(avctx, q); + return 0; } From 11aa9ca153d4446887ff3ebd26e5a3c243a19d80 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Sat, 18 Dec 2021 21:34:10 -0800 Subject: [PATCH 552/894] configure: fix metal detection and respect explicit disable Signed-off-by: Aman Karmani --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index d8b07c8e00..d9d41b2273 100755 --- a/configure +++ b/configure @@ -1758,6 +1758,7 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST=" libxcb_xfixes lzma mediafoundation + metal schannel sdl2 securetransport @@ -6328,13 +6329,13 @@ enabled appkit && check_apple_framework AppKit enabled audiotoolbox && check_apple_framework AudioToolbox enabled avfoundation && check_apple_framework AVFoundation enabled coreimage && check_apple_framework CoreImage +enabled metal && check_apple_framework Metal enabled videotoolbox && check_apple_framework VideoToolbox check_apple_framework CoreFoundation check_apple_framework CoreMedia check_apple_framework CoreVideo check_apple_framework CoreAudio -check_apple_framework Metal enabled avfoundation && { disable coregraphics applicationservices From 9c590b76f484a5021fa3e29f1043ddf6c33ae554 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Sun, 19 Dec 2021 09:41:16 -0800 Subject: [PATCH 553/894] avutil: add objc.h to SKIPHEADERS Signed-off-by: Aman Karmani --- libavutil/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/Makefile b/libavutil/Makefile index 529046dbc8..d17876df1a 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -195,6 +195,7 @@ OBJS += $(COMPAT_OBJS:%=../compat/%) # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avutilres.o +SKIPHEADERS += objc.h SKIPHEADERS-$(HAVE_CUDA_H) += hwcontext_cuda.h SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda_internal.h \ cuda_check.h From 631e31773b10d39067b5ab779c7e767350d895e8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 19 Dec 2021 00:11:37 +0100 Subject: [PATCH 554/894] avformat/sdp: Fix use of uninitialised value Fixes Coverity ticket #1495831. Regression since fe31708eaa10af42507b8db773d5af5a56e1aff4. Signed-off-by: Andreas Rheinhardt --- libavformat/sdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/sdp.c b/libavformat/sdp.c index ebde17bce4..111a25b126 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -237,7 +237,7 @@ static int extradata2psets_hevc(const AVCodecParameters *par, char **out) int ps_pos[3] = { 0 }; static const char * const ps_names[3] = { "vps", "sps", "pps" }; int num_arrays, num_nalus; - int pos, i, j, ret; + int pos, i, j, ret = 0; *out = NULL; From ba27e248cf5a817e13e4f22f08f6dd8a23da536c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 18 Dec 2021 11:56:19 +0100 Subject: [PATCH 555/894] avformat/crcenc: Make init function out of write_header Signed-off-by: Andreas Rheinhardt --- libavformat/crcenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/crcenc.c b/libavformat/crcenc.c index c58fbd6c88..9f40dd4ec0 100644 --- a/libavformat/crcenc.c +++ b/libavformat/crcenc.c @@ -28,7 +28,7 @@ typedef struct CRCState { uint32_t crcval; } CRCState; -static int crc_write_header(struct AVFormatContext *s) +static int crc_init(struct AVFormatContext *s) { CRCState *crc = s->priv_data; @@ -60,7 +60,7 @@ const AVOutputFormat ff_crc_muxer = { .priv_data_size = sizeof(CRCState), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, - .write_header = crc_write_header, + .init = crc_init, .write_packet = crc_write_packet, .write_trailer = crc_write_trailer, .flags = AVFMT_NOTIMESTAMPS, From 16b1df7541f81512b7869525c8ca596e24a49eae Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 18 Dec 2021 11:57:56 +0100 Subject: [PATCH 556/894] avformat/wvenc: Make init function out of write_header Signed-off-by: Andreas Rheinhardt --- libavformat/wvenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c index 9a42f71440..0dca2f7996 100644 --- a/libavformat/wvenc.c +++ b/libavformat/wvenc.c @@ -30,7 +30,7 @@ typedef struct WvMuxContext { int64_t samples; } WvMuxContext; -static av_cold int wv_write_header(AVFormatContext *ctx) +static av_cold int wv_init(AVFormatContext *ctx) { if (ctx->nb_streams > 1 || ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) { @@ -84,7 +84,7 @@ const AVOutputFormat ff_wv_muxer = { .priv_data_size = sizeof(WvMuxContext), .audio_codec = AV_CODEC_ID_WAVPACK, .video_codec = AV_CODEC_ID_NONE, - .write_header = wv_write_header, + .init = wv_init, .write_packet = wv_write_packet, .write_trailer = wv_write_trailer, .flags = AVFMT_NOTIMESTAMPS, From c47896536ce7fe480242c61ba5ca404648db6c00 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Tue, 8 Jun 2021 22:11:34 +0800 Subject: [PATCH 557/894] MAINTAINERS: Add Haihao Xiang for qsv Signed-off-by: Zhong Li --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index dcac46003e..39ce91b755 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -226,7 +226,7 @@ Codecs: ptx.c Ivo van Poorten qcelp* Reynaldo H. Verdejo Pinochet qdm2.c, qdm2data.h Roberto Togni - qsv* Mark Thompson, Zhong Li + qsv* Mark Thompson, Zhong Li, Haihao Xiang qtrle.c Mike Melanson ra144.c, ra144.h, ra288.c, ra288.h Roberto Togni resample2.c Michael Niedermayer From 3c56b9c597565affdb97316fec11afb4cb5f1f00 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 20 Dec 2021 17:09:08 +0800 Subject: [PATCH 558/894] build: add .metal to vpath to fix build error Signed-off-by: Aman Karmani --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5b20658b52..5479554683 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ vpath %.v $(SRC_PATH) vpath %.texi $(SRC_PATH) vpath %.cu $(SRC_PATH) vpath %.ptx $(SRC_PATH) +vpath %.metal $(SRC_PATH) vpath %/fate_config.sh.template $(SRC_PATH) TESTTOOLS = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch From 35420ab7fd76bdcf43a2f671c39a2555a5fba488 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 20 Dec 2021 17:09:09 +0800 Subject: [PATCH 559/894] build: simplify rules for metal Signed-off-by: Aman Karmani --- ffbuild/common.mak | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ffbuild/common.mak b/ffbuild/common.mak index e79b509425..c13148f476 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -113,13 +113,13 @@ $(BIN2CEXE): ffbuild/bin2c_host.o $(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS) %.metal.air: %.metal - $(METALCC) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ + $(METALCC) $< -o $@ %.metallib: %.metal.air - $(METALLIB) --split-module-without-linking $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ + $(METALLIB) --split-module-without-linking $< -o $@ %.metallib.c: %.metallib $(BIN2CEXE) - $(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@))) + $(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@))) %.ptx: %.cu $(SRC_PATH)/compat/cuda/cuda_runtime.h $(COMPILE_NVCC) From 278068dc60d8737341d73e58f508d01ff883876c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 12 Dec 2021 17:26:03 +0800 Subject: [PATCH 560/894] avutil/display: fix inverted doc Signed-off-by: Andreas Rheinhardt --- doc/APIchanges | 5 +++++ libavutil/display.h | 2 +- libavutil/version.h | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 17aa664ca3..93fc45ced4 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,11 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-20 - xxxxxxxxxx - lavu 57.11.101 - display.h + Modified the documentation of av_display_rotation_set() + to match its longstanding actual behaviour of treating + the angle as directed clockwise. + 2021-12-xx - xxxxxxxxxx - lavf 59.10.100 - avformat.h Add AVFormatContext io_close2 which returns an int diff --git a/libavutil/display.h b/libavutil/display.h index 515adad795..d87bf68425 100644 --- a/libavutil/display.h +++ b/libavutil/display.h @@ -88,7 +88,7 @@ double av_display_rotation_get(const int32_t matrix[9]); /** - * Initialize a transformation matrix describing a pure counterclockwise + * Initialize a transformation matrix describing a pure clockwise * rotation by the specified angle (in degrees). * * @param matrix an allocated transformation matrix (will be fully overwritten diff --git a/libavutil/version.h b/libavutil/version.h index 0e7b36865a..678401fcf5 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 57 #define LIBAVUTIL_VERSION_MINOR 11 -#define LIBAVUTIL_VERSION_MICRO 100 +#define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From cde2efb5dac2358c919229015d18629ca739b602 Mon Sep 17 00:00:00 2001 From: "U. Artie Eoff" Date: Mon, 13 Dec 2021 20:08:06 -0800 Subject: [PATCH 561/894] MAINTAINERS: Add Haihao Xiang for vaapi Current listed maintainers for vaapi plugin are not reponsive and/or currently active in the ffmpeg community. Thus, vaapi plugin patches (and qsv plugin) have generally gone ignored or lost in the ether for too long. Remove Gwenole Beauchesne from vaapi maintainer who has not been active since 2016. Current alternative maintainer for vaapi is Mark Thompson whom has not been active since March/April 2021. Therefore, add Haihao Xiang to vaapi maintainer who's primary role is FFmpeg development with a focus on the vaapi and qsv plugins. Haihao has over a decade of media experience and many years of FFmpeg development experience, amongst other media frameworks. The additional patch for adding Haihao as qsv plugin maintainer has been submitted previously: https://patchwork.ffmpeg.org/project/ffmpeg/patch/20210608141134.27448-1-zhongli_dev@126.com/ This will help FFmpeg to continue to be the leading multimedia framework by allowing these plugins to be actively improved, enhanced, and maintained for existing and future HW platforms. Signed-off-by: U. Artie Eoff --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 39ce91b755..50ee5efecc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -274,8 +274,8 @@ Hardware acceleration: dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme d3d11va* Steve Lhomme mediacodec* Matthieu Bouron, Aman Gupta - vaapi* Gwenole Beauchesne - vaapi_encode* Mark Thompson + vaapi* Haihao Xiang + vaapi_encode* Mark Thompson, Haihao Xiang vdpau* Philip Langdale, Carl Eugen Hoyos videotoolbox* Rick Kern, Aman Gupta From 15cfb4eee316a1d6a0764f4460409f0258fd94cb Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Mon, 20 Dec 2021 23:52:44 +0100 Subject: [PATCH 562/894] checkasm: Use the correct AVTXContext in av_tx tests Keep a reference to the correct associated context of the reference function and use that context when calling the reference function. --- tests/checkasm/av_tx.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/checkasm/av_tx.c b/tests/checkasm/av_tx.c index 178fb61972..9d3823e8ed 100644 --- a/tests/checkasm/av_tx.c +++ b/tests/checkasm/av_tx.c @@ -22,6 +22,8 @@ #include "checkasm.h" +#include + #define EPS 0.00005 #define SCALE_NOOP(x) (x) @@ -41,6 +43,16 @@ static const int check_lens[] = { 2, 4, 8, 16, 32, 64, 1024, 16384, }; +static AVTXContext *tx_refs[6 /*AVTXType*/][FF_ARRAY_ELEMS(check_lens)]; +static int init = 0; + +static void free_tx_refs(void) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(tx_refs); i++) + for (int j = 0; j < FF_ARRAY_ELEMS(*tx_refs); j++) + av_tx_uninit(&tx_refs[i][j]); +} + #define CHECK_TEMPLATE(PREFIX, TYPE, DATA_TYPE, SCALE, LENGTHS, CHECK_EXPRESSION) \ do { \ int err; \ @@ -59,24 +71,26 @@ static const int check_lens[] = { } \ \ if (check_func(fn, PREFIX "_%i", len)) { \ + AVTXContext *tx_ref = tx_refs[TYPE][i]; \ + if (!tx_ref) \ + tx_ref = tx; \ num_checks++; \ last_check = len; \ - call_ref(tx, out_ref, in, sizeof(DATA_TYPE)); \ - call_new(tx, out_new, in, sizeof(DATA_TYPE)); \ + call_ref(tx_ref, out_ref, in, sizeof(DATA_TYPE)); \ + call_new(tx, out_new, in, sizeof(DATA_TYPE)); \ if (CHECK_EXPRESSION) { \ fail(); \ + av_tx_uninit(&tx); \ break; \ } \ bench_new(tx, out_new, in, sizeof(DATA_TYPE)); \ + av_tx_uninit(&tx_refs[TYPE][i]); \ + tx_refs[TYPE][i] = tx; \ + } else { \ + av_tx_uninit(&tx); \ } \ - \ - av_tx_uninit(&tx); \ - fn = NULL; \ } \ \ - av_tx_uninit(&tx); \ - fn = NULL; \ - \ if (num_checks == 1) \ report(PREFIX "_%i", last_check); \ else if (num_checks) \ @@ -105,4 +119,9 @@ void checkasm_check_av_tx(void) av_free(in); av_free(out_ref); av_free(out_new); + + if (!init) { + init = 1; + atexit(free_tx_refs); + } } From 3c9ffbd009243b3e83ba20956ff6401918376073 Mon Sep 17 00:00:00 2001 From: John-Paul Stewart Date: Sat, 18 Dec 2021 15:46:27 -0500 Subject: [PATCH 563/894] avformat/mvdec: read frame rate from data stream Prior to this patch, for version 2 of the file format the frame rate was hard-coded at 15 fps. This uses the 64-bit floating-point value from the data stream, similar to what is already done for version 3 of the file format (around line 206). Signed-off-by: John-Paul Stewart Reviewed-by: Peter Ross --- libavformat/mvdec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 5d184f20a4..a5c5b205a6 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -26,6 +26,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/eval.h" +#include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "libavutil/rational.h" @@ -300,8 +301,9 @@ static int mv_read_header(AVFormatContext *avctx) uint64_t timestamp; int v; uint32_t bytes_per_sample; + AVRational fps; - avio_skip(pb, 22); + avio_skip(pb, 10); /* allocate audio track first to prevent unnecessary seeking * (audio packet always precede video packet for a given frame) */ @@ -312,9 +314,11 @@ static int mv_read_header(AVFormatContext *avctx) vst = avformat_new_stream(avctx, NULL); if (!vst) return AVERROR(ENOMEM); - avpriv_set_pts_info(vst, 64, 1, 15); + fps = av_d2q(av_int2double(avio_rb64(pb)), INT_MAX); + avpriv_set_pts_info(vst, 64, fps.den, fps.num); + avio_skip(pb, 4); vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - vst->avg_frame_rate = av_inv_q(vst->time_base); + vst->avg_frame_rate = fps; vst->nb_frames = avio_rb32(pb); v = avio_rb32(pb); switch (v) { From 50bfd5e96e98e86df08cc7ffdf726f6ed6851ee7 Mon Sep 17 00:00:00 2001 From: John-Paul Stewart Date: Sat, 18 Dec 2021 15:46:28 -0500 Subject: [PATCH 564/894] avformat/mvdec: explicitly set duration Resolves a warning that duration is being innaccurately estimated based on bitrate. Signed-off-by: John-Paul Stewart Reviewed-by: Peter Ross --- libavformat/mvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index a5c5b205a6..1a5012e507 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -319,7 +319,7 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 4); vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; vst->avg_frame_rate = fps; - vst->nb_frames = avio_rb32(pb); + vst->duration = vst->nb_frames = avio_rb32(pb); v = avio_rb32(pb); switch (v) { case 1: From 155dcfe2e20b5a934310dd7561383b2c978c382d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 20 Dec 2021 18:08:36 +0100 Subject: [PATCH 565/894] avcodec/libx264: Don't unnecessarily add in-band extradata The check here is meant to check for whether avcintra-class option (default value -1) has been set; yet it checks for the x264_param_t value where 0 is the default value (treated as "no avcintra-mode" by x264). This meant that in-band extradata has been added unnecessarily when using global headers; furthermore, the first output packet had two x264 SEIs. Reviewed-by: Limin Wang Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 5f62c7b1d8..2b680abf21 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -944,7 +944,7 @@ static av_cold int X264_init(AVCodecContext *avctx) #if X264_BUILD >= 142 /* Separate headers not supported in AVC-Intra mode */ - if (x4->params.i_avcintra_class >= 0) + if (x4->avcintra_class >= 0) x4->params.b_repeat_headers = 1; #endif From fa2e460f635d6cc32d5eb2d4c61a12caba59810c Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 20 Dec 2021 11:04:49 +0100 Subject: [PATCH 566/894] configure: autodetect vulkan --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index d9d41b2273..05ac32b825 100755 --- a/configure +++ b/configure @@ -324,7 +324,7 @@ External library support: --disable-securetransport disable Secure Transport, needed for TLS support on OSX if openssl and gnutls are not used [autodetect] --enable-vapoursynth enable VapourSynth demuxer [no] - --enable-vulkan enable Vulkan code [no] + --disable-vulkan disable Vulkan code [autodetect] --disable-xlib disable xlib [autodetect] --disable-zlib disable zlib [autodetect] @@ -1897,6 +1897,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" vaapi vdpau videotoolbox + vulkan v4l2_m2m xvmc " @@ -1919,7 +1920,6 @@ HWACCEL_LIBRARY_LIST=" mmal omx opencl - vulkan " DOCUMENT_LIST=" @@ -6915,7 +6915,7 @@ enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if. if enabled vulkan; then check_pkg_config_header_only vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || - require_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_2" + check_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_2" fi if enabled x86; then From 14b6805eb29d193105998e530e92525d7fe98d6d Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 21 Dec 2021 15:28:50 +0100 Subject: [PATCH 567/894] configure: improve non-pkgconfig Vulkan version check Check for the patch version as well as the major+minor version. The VK_API_VERSION macros are not usable in preprocessor code due to casts. The patch (header) version is meant to linearly increment and not be reset, however it's better to trust, but verify. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 05ac32b825..0ccd3bda11 100755 --- a/configure +++ b/configure @@ -6915,7 +6915,7 @@ enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if. if enabled vulkan; then check_pkg_config_header_only vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || - check_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_2" + check_cpp_condition vulkan "vulkan/vulkan.h" "defined(VK_VERSION_1_3) || (defined(VK_VERSION_1_2) && VK_HEADER_VERSION >= 189)" fi if enabled x86; then From ffbab99f2c22be06ef3c564fd38320d40e48a2b5 Mon Sep 17 00:00:00 2001 From: Alan Kelly Date: Tue, 21 Dec 2021 20:56:41 +0100 Subject: [PATCH 568/894] libavutil/cpu: Add AV_CPU_FLAG_SLOW_GATHER. This flag is set on Haswell and earlier and all AMD cpus. --- doc/APIchanges | 3 +++ libavutil/cpu.h | 1 + libavutil/version.h | 4 ++-- libavutil/x86/cpu.c | 15 ++++++++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 93fc45ced4..ac75040274 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-21 - xxxxxxxxxx - lavu 57.12.100 - cpu.h + Add AV_CPU_FLAG_SLOW_GATHER. + 2021-12-20 - xxxxxxxxxx - lavu 57.11.101 - display.h Modified the documentation of av_display_rotation_set() to match its longstanding actual behaviour of treating diff --git a/libavutil/cpu.h b/libavutil/cpu.h index ae443eccad..ce9bf14bf7 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -54,6 +54,7 @@ #define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1 #define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2 #define AV_CPU_FLAG_AVX512 0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used +#define AV_CPU_FLAG_SLOW_GATHER 0x2000000 ///< CPU has slow gathers. #define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard #define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06 diff --git a/libavutil/version.h b/libavutil/version.h index 678401fcf5..668f9206fe 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,8 +79,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 11 -#define LIBAVUTIL_VERSION_MICRO 101 +#define LIBAVUTIL_VERSION_MINOR 12 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index bcd41a50a2..441b4695d5 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -146,8 +146,21 @@ int ff_get_cpu_flags_x86(void) if (max_std_level >= 7) { cpuid(7, eax, ebx, ecx, edx); #if HAVE_AVX2 - if ((rval & AV_CPU_FLAG_AVX) && (ebx & 0x00000020)) + if ((rval & AV_CPU_FLAG_AVX) && (ebx & 0x00000020)) { rval |= AV_CPU_FLAG_AVX2; + cpuid(1, eax, ebx, ecx, std_caps); + family = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); + model = ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0); + /* Haswell has slow gather */ + if (!strncmp(vendor.c, "GenuineIntel", 12)) + if (family == 6 && model < 70) + rval |= AV_CPU_FLAG_SLOW_GATHER; + /* Zen 3 and earlier have slow gather */ + if (!strncmp(vendor.c, "AuthenticAMD", 12)) + if (family <= 0x19) + rval |= AV_CPU_FLAG_SLOW_GATHER; + } + #if HAVE_AVX512 /* F, CD, BW, DQ, VL */ if ((xcr0_lo & 0xe0) == 0xe0) { /* OPMASK/ZMM state */ if ((rval & AV_CPU_FLAG_AVX2) && (ebx & 0xd0030000) == 0xd0030000) From eebe406c808e6061ee76e93a616537b5369dbf40 Mon Sep 17 00:00:00 2001 From: Alan Kelly Date: Mon, 20 Dec 2021 15:45:45 +0100 Subject: [PATCH 569/894] libswscale: Test AV_CPU_FLAG_SLOW_GATHER for hscale functions. This is instead of EXTERNAL_AVX2_FAST so that the avx2 hscale functions are only used where they are faster. --- libswscale/utils.c | 2 +- libswscale/x86/swscale.c | 2 +- tests/checkasm/sw_scale.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index d4a72d3ce1..7158384f0b 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -282,7 +282,7 @@ void ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos, int filterSiz #if ARCH_X86_64 int i, j, k, l; int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_AVX2_FAST(cpu_flags)){ + if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) { if ((c->srcBpc == 8) && (c->dstBpc <= 14)){ if (dstW % 16 == 0){ if (filter != NULL){ diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index c49a05c37b..ffc7691c12 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -578,7 +578,7 @@ switch(c->dstBpc){ \ break; \ } - if (EXTERNAL_AVX2_FAST(cpu_flags)) { + if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) { if ((c->srcBpc == 8) && (c->dstBpc <= 14)) { if (c->chrDstW % 16 == 0) ASSIGN_AVX2_SCALE_FUNC(c->hcScale, c->hChrFilterSize); diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index f4912e6c2c..3c0a083b42 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -217,7 +217,7 @@ static void check_hscale(void) } ff_sws_init_scale(ctx); memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); - if (cpu_flags & AV_CPU_FLAG_AVX2) + if ((cpu_flags & AV_CPU_FLAG_AVX2) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) ff_shuffle_filter_coefficients(ctx, filterPosAvx, width, filterAvx2, SRC_PIXELS); if (check_func(ctx->hcScale, "hscale_%d_to_%d_width%d", ctx->srcBpc, ctx->dstBpc + 1, width)) { From 8c2d2fd6ccca4e389cb9dac4ab190965e97868a4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Dec 2021 17:39:02 -0300 Subject: [PATCH 570/894] avutil/cpu: move slow gather checks below in the function Put them together with other similar slow flag checks. Signed-off-by: James Almer --- libavutil/x86/cpu.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 441b4695d5..7b13fcae91 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -146,21 +146,8 @@ int ff_get_cpu_flags_x86(void) if (max_std_level >= 7) { cpuid(7, eax, ebx, ecx, edx); #if HAVE_AVX2 - if ((rval & AV_CPU_FLAG_AVX) && (ebx & 0x00000020)) { + if ((rval & AV_CPU_FLAG_AVX) && (ebx & 0x00000020)) rval |= AV_CPU_FLAG_AVX2; - cpuid(1, eax, ebx, ecx, std_caps); - family = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); - model = ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0); - /* Haswell has slow gather */ - if (!strncmp(vendor.c, "GenuineIntel", 12)) - if (family == 6 && model < 70) - rval |= AV_CPU_FLAG_SLOW_GATHER; - /* Zen 3 and earlier have slow gather */ - if (!strncmp(vendor.c, "AuthenticAMD", 12)) - if (family <= 0x19) - rval |= AV_CPU_FLAG_SLOW_GATHER; - } - #if HAVE_AVX512 /* F, CD, BW, DQ, VL */ if ((xcr0_lo & 0xe0) == 0xe0) { /* OPMASK/ZMM state */ if ((rval & AV_CPU_FLAG_AVX2) && (ebx & 0xd0030000) == 0xd0030000) @@ -209,6 +196,10 @@ int ff_get_cpu_flags_x86(void) used unless explicitly disabled by checking AV_CPU_FLAG_AVXSLOW. */ if ((family == 0x15 || family == 0x16) && (rval & AV_CPU_FLAG_AVX)) rval |= AV_CPU_FLAG_AVXSLOW; + + /* Zen 3 and earlier have slow gather */ + if ((family <= 0x19) && (rval & AV_CPU_FLAG_AVX2)) + rval |= AV_CPU_FLAG_SLOW_GATHER; } /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be @@ -248,6 +239,10 @@ int ff_get_cpu_flags_x86(void) if ((rval & AV_CPU_FLAG_SSSE3) && !(rval & AV_CPU_FLAG_SSE4) && family == 6 && model < 23) rval |= AV_CPU_FLAG_SSSE3SLOW; + + /* Haswell has slow gather */ + if ((rval & AV_CPU_FLAG_AVX2) && family == 6 && model < 70) + rval |= AV_CPU_FLAG_SLOW_GATHER; } #endif /* cpuid */ From e68e379e0c3da6a8dd77a73adf312c14070ecfd6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Dec 2021 17:51:03 -0300 Subject: [PATCH 571/894] avutil/cpu: add slowgather to av_parse_cpu_caps() Signed-off-by: James Almer --- libavutil/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 63efb97ffd..1368502245 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -137,6 +137,7 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) { "cmov", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_CMOV }, .unit = "flags" }, { "aesni", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AESNI }, .unit = "flags" }, { "avx512" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX512 }, .unit = "flags" }, + { "slowgather", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SLOW_GATHER }, .unit = "flags" }, #define CPU_FLAG_P2 AV_CPU_FLAG_CMOV | AV_CPU_FLAG_MMX #define CPU_FLAG_P3 CPU_FLAG_P2 | AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE From e1d3ef921749a6f5c4432b0480129030ef94641e Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Dec 2021 17:52:09 -0300 Subject: [PATCH 572/894] avutil/tests/cpu: add slowgather Signed-off-by: James Almer --- libavutil/tests/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c index 0a6c0cd32e..5bec742b2b 100644 --- a/libavutil/tests/cpu.c +++ b/libavutil/tests/cpu.c @@ -77,6 +77,7 @@ static const struct { { AV_CPU_FLAG_BMI2, "bmi2" }, { AV_CPU_FLAG_AESNI, "aesni" }, { AV_CPU_FLAG_AVX512, "avx512" }, + { AV_CPU_FLAG_SLOW_GATHER, "slowgather" }, #elif ARCH_LOONGARCH { AV_CPU_FLAG_LSX, "lsx" }, { AV_CPU_FLAG_LASX, "lasx" }, From 0e1f5f887188fcda9262ae662769eb3f186b9ef0 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Thu, 9 Dec 2021 12:01:27 +0800 Subject: [PATCH 573/894] fate: use single thread for rawvideo Signed-off-by: Limin Wang --- tests/fate/ffmpeg.mak | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 4ba73a8dfa..2a6a06642e 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -32,7 +32,7 @@ fate-ffmpeg-filter_complex_audio: CMD = framecrc -auto_conversion_filters -filte # Ticket 6375, use case of NoX FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PNG_DECODER ALAC_DECODER PCM_S16LE_ENCODER RAWVIDEO_ENCODER) += fate-ffmpeg-attached_pics -fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -c:a pcm_s16le -max_muxing_queue_size 16 -af aresample +fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -c:a pcm_s16le -threads 1 -max_muxing_queue_size 16 -af aresample FATE_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey @@ -54,7 +54,7 @@ fate-sub2video: CMD = framecrc -auto_conversion_filters \ -f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ -ss 132 -i $(TARGET_SAMPLES)/sub/vobsub.idx \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:0]scale=720:480[v]\;[v][1:0]overlay[v2]" \ - -map "[v2]" -c:v rawvideo -map 1:s -c:s dvdsub + -map "[v2]" -c:v rawvideo -threads 1 -map 1:s -c:s dvdsub # Very basic sub2video example, decode and convert to AVFrame with sub2video. # Attempt to not touch timestamps. @@ -63,7 +63,7 @@ fate-sub2video_basic: CMD = framecrc -auto_conversion_filters \ -i $(TARGET_SAMPLES)/sub/vobsub.idx \ -vsync passthrough -copyts \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:s:0]scale" \ - -c:v rawvideo + -c:v rawvideo -threads 1 # Time-limited run with a sample that doesn't require seeking and # contains samples within the initial period. @@ -73,7 +73,7 @@ fate-sub2video_time_limited: CMD = framecrc -auto_conversion_filters \ -vsync passthrough -copyts \ -t 15 \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:s:0]scale" \ - -c:v rawvideo + -c:v rawvideo -threads 1 FATE_FFMPEG-$(call ALLYES, PCM_S16LE_DEMUXER PCM_S16LE_MUXER PCM_S16LE_DECODER PCM_S16LE_ENCODER) += fate-unknown_layout-pcm fate-unknown_layout-pcm: $(AREF) @@ -170,7 +170,7 @@ fate-streamcopy: $(FATE_STREAMCOPY-yes) FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER MATROSKA_MUXER) += fate-rgb24-mkv fate-rgb24-mkv: $(SAMPLES)/qtrle/aletrek-rle.mov fate-rgb24-mkv: CMD = transcode "mov" $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov\ - matroska "-c:v rawvideo -pix_fmt rgb24 -allow_raw_vfw 1 -frames:v 1" + matroska "-c:v rawvideo -threads 1 -pix_fmt rgb24 -allow_raw_vfw 1 -frames:v 1" FATE_SAMPLES_FFMPEG-$(call ALLYES, AAC_DEMUXER MOV_MUXER) += fate-adtstoasc_ticket3715 fate-adtstoasc_ticket3715: $(SAMPLES)/aac/foo.aac From 8ecd7cdb469ede77ca91f80f8095adf76e2eac9f Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sun, 5 Dec 2021 08:32:53 +0800 Subject: [PATCH 574/894] avcodec/rawenc: suppport frame thread for rawvideo Signed-off-by: Limin Wang --- libavcodec/rawenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c index 7e15084d71..561d992a46 100644 --- a/libavcodec/rawenc.c +++ b/libavcodec/rawenc.c @@ -85,7 +85,7 @@ const AVCodec ff_rawvideo_encoder = { .long_name = NULL_IF_CONFIG_SMALL("raw video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_RAWVIDEO, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init = raw_encode_init, .encode2 = raw_encode, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, From 2ac8bcec6374da529e08a684d587488287b8ed7f Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 7 Dec 2021 21:48:13 +0800 Subject: [PATCH 575/894] avcodec/v210enc: suppport frame thread for v210 Signed-off-by: Limin Wang --- libavcodec/v210enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index 22875be7d5..16c4f82cf2 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -156,7 +156,7 @@ const AVCodec ff_v210_encoder = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_V210, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(V210EncContext), .init = encode_init, .encode2 = encode_frame, From 18ad360648cd185b0ffbb444eedcbf5732774408 Mon Sep 17 00:00:00 2001 From: Gerard Sole Date: Wed, 15 Dec 2021 20:00:31 +0100 Subject: [PATCH 576/894] libavformat: add side_data copy in concat demuxer Adds support for concat demuxer to copy the side data information from the input file to the resulting file. It will behave like the metadata copy, where the metadata of the first file is kept in the the output file. Extract the current code that already performs the stream side_data copy into a separate method and reuse the method in the concat demuxer. Signed-off-by: Gerard Sole --- libavformat/concatdec.c | 1 + libavformat/internal.h | 9 +++++++++ libavformat/utils.c | 9 +++++++++ tests/ref/fate/concat-demuxer-extended-lavf-mxf | 2 +- tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 | 2 +- tests/ref/fate/concat-demuxer-simple1-lavf-mxf | 1 + tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 | 1 + tests/ref/fate/concat-demuxer-simple2-lavf-ts | 1 + 8 files changed, 24 insertions(+), 2 deletions(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 8d80e536d1..0603c6e254 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -191,6 +191,7 @@ static int copy_stream_props(AVStream *st, AVStream *source_st) avpriv_set_pts_info(st, 64, source_st->time_base.num, source_st->time_base.den); av_dict_copy(&st->metadata, source_st->metadata, 0); + ff_stream_side_data_copy(st, source_st); return 0; } diff --git a/libavformat/internal.h b/libavformat/internal.h index 92eeb82550..2ba795d669 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -841,6 +841,15 @@ int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *a */ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src); +/** + * Copy side data from source to destination stream + * + * @param dst pointer to destination AVStream + * @param src pointer to source AVStream + * @return >=0 on success, AVERROR code on error + */ +int ff_stream_side_data_copy(AVStream *dst, const AVStream *src); + /** * Wrap ffurl_move() and log if error happens. * diff --git a/libavformat/utils.c b/libavformat/utils.c index b5a4a09ae8..332ba534d2 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -605,6 +605,15 @@ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src) if (ret < 0) return ret; + ret = ff_stream_side_data_copy(dst, src); + if (ret < 0) + return ret; + + return 0; +} + +int ff_stream_side_data_copy(AVStream *dst, const AVStream *src) +{ /* Free existing side data*/ for (int i = 0; i < dst->nb_side_data; i++) av_free(dst->side_data[i].data); diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf b/tests/ref/fate/concat-demuxer-extended-lavf-mxf index 4b2a8624db..543c7d6a8c 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf @@ -1 +1 @@ -29e4e502a912b6d863e75d44e156ed31 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe +d367d7f6df7292cbf454c6d07fca9b04 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 index 1dedc6bf43..57b22848b9 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 @@ -1 +1 @@ -8de04a786521677a593283c44a53572e *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe +1fac6962d4c5f1070d0d2db5ab7d86aa *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf index 2fe703e2a6..589dbb73b6 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf @@ -121,4 +121,5 @@ Strings Metadata video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1 Strings Metadata 0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 +CPB properties|0|0|0|49152|-1 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|1|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|768000|N/A|N/A|N/A|N/A|50|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 index 0a3af658f6..7fb6ba2c9c 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 @@ -79,4 +79,5 @@ Strings Metadata audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1 Strings Metadata 0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 +CPB properties|30000000|0|0|1212416|-1 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|2|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|1536000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple2-lavf-ts b/tests/ref/fate/concat-demuxer-simple2-lavf-ts index 76dde3b873..7c6079e2b1 100644 --- a/tests/ref/fate/concat-demuxer-simple2-lavf-ts +++ b/tests/ref/fate/concat-demuxer-simple2-lavf-ts @@ -213,3 +213,4 @@ video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__MPEGTS Stre 0|mp2|unknown|audio|[3][0][0][0]|0x0003|s16p|44100|1|mono|0|N/A|0/0|0/0|1/90000|0|0.000000|N/A|N/A|64000|N/A|N/A|N/A|N/A|89|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 0 1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1 +CPB properties|0|0|0|49152|-1 From 131dbb9a7a2dd645c36a85190e2fe0ab987c45cf Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 20 Dec 2021 15:07:10 -0300 Subject: [PATCH 577/894] ffprobe: add missing separator when printing side data in compact output Should fix ticket #7153 Signed-off-by: James Almer --- fftools/ffprobe.c | 4 +- .../ref/fate/concat-demuxer-simple1-lavf-mxf | 66 +- .../fate/concat-demuxer-simple1-lavf-mxf_d10 | 33 +- tests/ref/fate/concat-demuxer-simple2-lavf-ts | 131 ++- tests/ref/fate/flv-demux | 4 +- tests/ref/fate/gapless-mp3-side-data | 6 +- tests/ref/fate/gaplessenc-itunes-to-ipod-aac | 2 +- tests/ref/fate/gaplessenc-pcm-to-mov-aac | 2 +- tests/ref/fate/gaplessinfo-itunes1 | 2 +- tests/ref/fate/gaplessinfo-itunes2 | 2 +- tests/ref/fate/mov-aac-2048-priming | 2 +- tests/ref/fate/mov-zombie | 133 ++- tests/ref/fate/oggopus-demux | 4 +- tests/ref/fate/ts-demux | 39 +- tests/ref/fate/ts-opus-demux | 1024 ++++++++--------- tests/ref/fate/ts-small-demux | 146 +-- 16 files changed, 783 insertions(+), 817 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 0711e02922..906bb03b16 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -1151,8 +1151,10 @@ static void compact_print_section_header(WriterContext *wctx) if (parent_section && compact->has_nested_elems[wctx->level-1] && (section->flags & SECTION_FLAG_IS_ARRAY)) { compact->terminate_line[wctx->level-1] = 0; - printf("\n"); } + if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) && + wctx->level && wctx->nb_item[wctx->level-1]) + printf("%c", compact->item_sep); if (compact->print_section && !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) printf("%s%c", section->name, compact->item_sep); diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf index 589dbb73b6..dcc98e9bdb 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf @@ -78,48 +78,26 @@ video|0|27|1.080000|27|1.080000|1|0.040000|10840|491008|__ audio|1|53760|1.120000|53760|1.120000|1920|0.040000|3840|502272|K_ video|0|28|1.120000|28|1.120000|1|0.040000|13350|506880|__ audio|1|55680|1.160000|55680|1.160000|1920|0.040000|3840|520704|K_ -video|0|25|1.000000|24|0.960000|1|0.040000|24801|7168|K_|1 -Strings Metadata -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|32256|K_|1 -Strings Metadata -video|0|28|1.120000|25|1.000000|1|0.040000|16743|36864|__|1 -Strings Metadata -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|53760|K_|1 -Strings Metadata -video|0|26|1.040000|26|1.040000|1|0.040000|13812|58368|__|1 -Strings Metadata -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|72704|K_|1 -Strings Metadata -video|0|27|1.080000|27|1.080000|1|0.040000|13607|77312|__|1 -Strings Metadata -audio|1|53760|1.120000|53760|1.120000|1920|0.040000|3840|91136|K_|1 -Strings Metadata -video|0|31|1.240000|28|1.120000|1|0.040000|16158|95744|__|1 -Strings Metadata -audio|1|55680|1.160000|55680|1.160000|1920|0.040000|3840|112128|K_|1 -Strings Metadata -video|0|29|1.160000|29|1.160000|1|0.040000|13943|116736|__|1 -Strings Metadata -audio|1|57600|1.200000|57600|1.200000|1920|0.040000|3840|131072|K_|1 -Strings Metadata -video|0|30|1.200000|30|1.200000|1|0.040000|11223|135680|__|1 -Strings Metadata -audio|1|59520|1.240000|59520|1.240000|1920|0.040000|3840|146944|K_|1 -Strings Metadata -video|0|34|1.360000|31|1.240000|1|0.040000|20298|151552|__|1 -Strings Metadata -audio|1|61440|1.280000|61440|1.280000|1920|0.040000|3840|172032|K_|1 -Strings Metadata -video|0|32|1.280000|32|1.280000|1|0.040000|13341|176640|__|1 -Strings Metadata -audio|1|63360|1.320000|63360|1.320000|1920|0.040000|3840|190464|K_|1 -Strings Metadata -video|0|33|1.320000|33|1.320000|1|0.040000|12362|195072|__|1 -Strings Metadata -audio|1|65280|1.360000|65280|1.360000|1920|0.040000|3840|207872|K_|1 -Strings Metadata -video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1 -Strings Metadata -0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 -CPB properties|0|0|0|49152|-1 +video|0|25|1.000000|24|0.960000|1|0.040000|24801|7168|K_|1|Strings Metadata +audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|32256|K_|1|Strings Metadata +video|0|28|1.120000|25|1.000000|1|0.040000|16743|36864|__|1|Strings Metadata +audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|53760|K_|1|Strings Metadata +video|0|26|1.040000|26|1.040000|1|0.040000|13812|58368|__|1|Strings Metadata +audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|72704|K_|1|Strings Metadata +video|0|27|1.080000|27|1.080000|1|0.040000|13607|77312|__|1|Strings Metadata +audio|1|53760|1.120000|53760|1.120000|1920|0.040000|3840|91136|K_|1|Strings Metadata +video|0|31|1.240000|28|1.120000|1|0.040000|16158|95744|__|1|Strings Metadata +audio|1|55680|1.160000|55680|1.160000|1920|0.040000|3840|112128|K_|1|Strings Metadata +video|0|29|1.160000|29|1.160000|1|0.040000|13943|116736|__|1|Strings Metadata +audio|1|57600|1.200000|57600|1.200000|1920|0.040000|3840|131072|K_|1|Strings Metadata +video|0|30|1.200000|30|1.200000|1|0.040000|11223|135680|__|1|Strings Metadata +audio|1|59520|1.240000|59520|1.240000|1920|0.040000|3840|146944|K_|1|Strings Metadata +video|0|34|1.360000|31|1.240000|1|0.040000|20298|151552|__|1|Strings Metadata +audio|1|61440|1.280000|61440|1.280000|1920|0.040000|3840|172032|K_|1|Strings Metadata +video|0|32|1.280000|32|1.280000|1|0.040000|13341|176640|__|1|Strings Metadata +audio|1|63360|1.320000|63360|1.320000|1920|0.040000|3840|190464|K_|1|Strings Metadata +video|0|33|1.320000|33|1.320000|1|0.040000|12362|195072|__|1|Strings Metadata +audio|1|65280|1.360000|65280|1.360000|1920|0.040000|3840|207872|K_|1|Strings Metadata +video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1|Strings Metadata +0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001|CPB properties|0|0|0|49152|-1 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|1|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|768000|N/A|N/A|N/A|N/A|50|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 index 7fb6ba2c9c..8937724ed1 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 @@ -58,26 +58,15 @@ video|0|28|1.120000|28|1.120000|1|0.040000|150000|4905984|K_ audio|1|53760|1.120000|53760|1.120000|1920|0.040000|7680|5056512|K_ video|0|29|1.160000|29|1.160000|1|0.040000|150000|5118976|K_ audio|1|55680|1.160000|55680|1.160000|1920|0.040000|7680|5269504|K_ -video|0|30|1.200000|30|1.200000|1|0.040000|150000|1072128|K_|1 -Strings Metadata -audio|1|57600|1.200000|57600|1.200000|1920|0.040000|7680|1222656|K_|1 -Strings Metadata -video|0|31|1.240000|31|1.240000|1|0.040000|150000|1285120|K_|1 -Strings Metadata -audio|1|59520|1.240000|59520|1.240000|1920|0.040000|7680|1435648|K_|1 -Strings Metadata -video|0|32|1.280000|32|1.280000|1|0.040000|150000|1498112|K_|1 -Strings Metadata -audio|1|61440|1.280000|61440|1.280000|1920|0.040000|7680|1648640|K_|1 -Strings Metadata -video|0|33|1.320000|33|1.320000|1|0.040000|150000|1711104|K_|1 -Strings Metadata -audio|1|63360|1.320000|63360|1.320000|1920|0.040000|7680|1861632|K_|1 -Strings Metadata -video|0|34|1.360000|34|1.360000|1|0.040000|150000|1924096|K_|1 -Strings Metadata -audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1 -Strings Metadata -0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 -CPB properties|30000000|0|0|1212416|-1 +video|0|30|1.200000|30|1.200000|1|0.040000|150000|1072128|K_|1|Strings Metadata +audio|1|57600|1.200000|57600|1.200000|1920|0.040000|7680|1222656|K_|1|Strings Metadata +video|0|31|1.240000|31|1.240000|1|0.040000|150000|1285120|K_|1|Strings Metadata +audio|1|59520|1.240000|59520|1.240000|1920|0.040000|7680|1435648|K_|1|Strings Metadata +video|0|32|1.280000|32|1.280000|1|0.040000|150000|1498112|K_|1|Strings Metadata +audio|1|61440|1.280000|61440|1.280000|1920|0.040000|7680|1648640|K_|1|Strings Metadata +video|0|33|1.320000|33|1.320000|1|0.040000|150000|1711104|K_|1|Strings Metadata +audio|1|63360|1.320000|63360|1.320000|1920|0.040000|7680|1861632|K_|1|Strings Metadata +video|0|34|1.360000|34|1.360000|1|0.040000|150000|1924096|K_|1|Strings Metadata +audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1|Strings Metadata +0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001|CPB properties|30000000|0|0|1212416|-1 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|2|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|1536000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple2-lavf-ts b/tests/ref/fate/concat-demuxer-simple2-lavf-ts index 7c6079e2b1..9603ca21d0 100644 --- a/tests/ref/fate/concat-demuxer-simple2-lavf-ts +++ b/tests/ref/fate/concat-demuxer-simple2-lavf-ts @@ -1,20 +1,20 @@ -video|1|982|0.010911|-2618|-0.029089|3600|0.040000|24801|564|K_MPEGTS Stream ID|224 +video|1|982|0.010911|-2618|-0.029089|3600|0.040000|24801|564|K_|MPEGTS Stream ID|224 -video|1|4582|0.050911|982|0.010911|3600|0.040000|16429|25944|__MPEGTS Stream ID|224 +video|1|4582|0.050911|982|0.010911|3600|0.040000|16429|25944|__|MPEGTS Stream ID|224 -video|1|8182|0.090911|4582|0.050911|3600|0.040000|14508|42864|__MPEGTS Stream ID|224 +video|1|8182|0.090911|4582|0.050911|3600|0.040000|14508|42864|__|MPEGTS Stream ID|224 -video|1|11782|0.130911|8182|0.090911|3600|0.040000|12622|58092|__MPEGTS Stream ID|224 +video|1|11782|0.130911|8182|0.090911|3600|0.040000|12622|58092|__|MPEGTS Stream ID|224 -video|1|15382|0.170911|11782|0.130911|3600|0.040000|13393|71064|__MPEGTS Stream ID|224 +video|1|15382|0.170911|11782|0.130911|3600|0.040000|13393|71064|__|MPEGTS Stream ID|224 -video|1|18982|0.210911|15382|0.170911|3600|0.040000|13092|84788|__MPEGTS Stream ID|224 +video|1|18982|0.210911|15382|0.170911|3600|0.040000|13092|84788|__|MPEGTS Stream ID|224 -video|1|22582|0.250911|18982|0.210911|3600|0.040000|12755|98700|__MPEGTS Stream ID|224 +video|1|22582|0.250911|18982|0.210911|3600|0.040000|12755|98700|__|MPEGTS Stream ID|224 -video|1|26182|0.290911|22582|0.250911|3600|0.040000|12023|111860|__MPEGTS Stream ID|224 +video|1|26182|0.290911|22582|0.250911|3600|0.040000|12023|111860|__|MPEGTS Stream ID|224 -audio|0|0|0.000000|0|0.000000|2351|0.026122|208|152844|K_MPEGTS Stream ID|192 +audio|0|0|0.000000|0|0.000000|2351|0.026122|208|152844|K_|MPEGTS Stream ID|192 audio|0|2351|0.026122|2351|0.026122|2351|0.026122|209|N/A|K_ audio|0|4702|0.052244|4702|0.052244|2351|0.026122|209|N/A|K_ @@ -29,27 +29,27 @@ audio|0|23510|0.261222|23510|0.261222|2351|0.026122|209|N/A|K_ audio|0|25861|0.287344|25861|0.287344|2351|0.026122|209|N/A|K_ audio|0|28212|0.313467|28212|0.313467|2351|0.026122|209|N/A|K_ audio|0|30563|0.339589|30563|0.339589|2351|0.026122|209|N/A|K_ -video|1|29782|0.330911|26182|0.290911|3600|0.040000|14098|124268|__MPEGTS Stream ID|224 +video|1|29782|0.330911|26182|0.290911|3600|0.040000|14098|124268|__|MPEGTS Stream ID|224 -video|1|33382|0.370911|29782|0.330911|3600|0.040000|13329|139120|__MPEGTS Stream ID|224 +video|1|33382|0.370911|29782|0.330911|3600|0.040000|13329|139120|__|MPEGTS Stream ID|224 -video|1|36982|0.410911|33382|0.370911|3600|0.040000|12135|155852|__MPEGTS Stream ID|224 +video|1|36982|0.410911|33382|0.370911|3600|0.040000|12135|155852|__|MPEGTS Stream ID|224 -video|1|40582|0.450911|36982|0.410911|3600|0.040000|12282|168448|__MPEGTS Stream ID|224 +video|1|40582|0.450911|36982|0.410911|3600|0.040000|12282|168448|__|MPEGTS Stream ID|224 -video|1|44182|0.490911|40582|0.450911|3600|0.040000|24786|181420|K_MPEGTS Stream ID|224 +video|1|44182|0.490911|40582|0.450911|3600|0.040000|24786|181420|K_|MPEGTS Stream ID|224 -video|1|47782|0.530911|44182|0.490911|3600|0.040000|17440|206988|__MPEGTS Stream ID|224 +video|1|47782|0.530911|44182|0.490911|3600|0.040000|17440|206988|__|MPEGTS Stream ID|224 -video|1|51382|0.570911|47782|0.530911|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 +video|1|51382|0.570911|47782|0.530911|3600|0.040000|15019|224848|__|MPEGTS Stream ID|224 -video|1|54982|0.610911|51382|0.570911|3600|0.040000|13449|240640|__MPEGTS Stream ID|224 +video|1|54982|0.610911|51382|0.570911|3600|0.040000|13449|240640|__|MPEGTS Stream ID|224 -video|1|58582|0.650911|54982|0.610911|3600|0.040000|12398|254552|__MPEGTS Stream ID|224 +video|1|58582|0.650911|54982|0.610911|3600|0.040000|12398|254552|__|MPEGTS Stream ID|224 -video|1|62182|0.690911|58582|0.650911|3600|0.040000|13455|267336|__MPEGTS Stream ID|224 +video|1|62182|0.690911|58582|0.650911|3600|0.040000|13455|267336|__|MPEGTS Stream ID|224 -audio|0|32915|0.365722|32915|0.365722|2351|0.026122|209|308508|K_MPEGTS Stream ID|192 +audio|0|32915|0.365722|32915|0.365722|2351|0.026122|209|308508|K_|MPEGTS Stream ID|192 audio|0|35266|0.391844|35266|0.391844|2351|0.026122|209|N/A|K_ audio|0|37617|0.417967|37617|0.417967|2351|0.026122|209|N/A|K_ @@ -64,17 +64,17 @@ audio|0|56425|0.626944|56425|0.626944|2351|0.026122|209|N/A|K_ audio|0|58776|0.653067|58776|0.653067|2351|0.026122|209|N/A|K_ audio|0|61127|0.679189|61127|0.679189|2351|0.026122|209|N/A|K_ audio|0|63478|0.705311|63478|0.705311|2351|0.026122|209|N/A|K_ -video|1|65782|0.730911|62182|0.690911|3600|0.040000|13836|281624|__MPEGTS Stream ID|224 +video|1|65782|0.730911|62182|0.690911|3600|0.040000|13836|281624|__|MPEGTS Stream ID|224 -video|1|69382|0.770911|65782|0.730911|3600|0.040000|12163|295912|__MPEGTS Stream ID|224 +video|1|69382|0.770911|65782|0.730911|3600|0.040000|12163|295912|__|MPEGTS Stream ID|224 -video|1|72982|0.810911|69382|0.770911|3600|0.040000|12692|311516|__MPEGTS Stream ID|224 +video|1|72982|0.810911|69382|0.770911|3600|0.040000|12692|311516|__|MPEGTS Stream ID|224 -video|1|76582|0.850911|72982|0.810911|3600|0.040000|10824|325052|__MPEGTS Stream ID|224 +video|1|76582|0.850911|72982|0.810911|3600|0.040000|10824|325052|__|MPEGTS Stream ID|224 -video|1|80182|0.890911|76582|0.850911|3600|0.040000|11286|336144|__MPEGTS Stream ID|224 +video|1|80182|0.890911|76582|0.850911|3600|0.040000|11286|336144|__|MPEGTS Stream ID|224 -audio|0|65829|0.731433|65829|0.731433|2351|0.026122|209|386716|K_MPEGTS Stream ID|192 +audio|0|65829|0.731433|65829|0.731433|2351|0.026122|209|386716|K_|MPEGTS Stream ID|192 audio|0|68180|0.757556|68180|0.757556|2351|0.026122|209|N/A|K_ audio|0|70531|0.783678|70531|0.783678|2351|0.026122|209|N/A|K_ @@ -86,26 +86,26 @@ audio|0|82286|0.914289|82286|0.914289|2351|0.026122|209|N/A|K_ audio|0|84637|0.940411|84637|0.940411|2351|0.026122|209|N/A|K_ audio|0|86988|0.966533|86988|0.966533|2351|0.026122|209|N/A|K_ audio|0|89339|0.992656|89339|0.992656|2351|0.026122|209|N/A|K_ -video|1|83782|0.930911|80182|0.890911|3600|0.040000|12678|347800|__MPEGTS Stream ID|224 +video|1|83782|0.930911|80182|0.890911|3600|0.040000|12678|347800|__|MPEGTS Stream ID|224 video|1|87382|0.970911|83782|0.930911|3600|0.040000|24711|361336|K_ -video|1|91964|1.021822|88364|0.981822|3600|0.040000|24801|564|K_MPEGTS Stream ID|224 +video|1|91964|1.021822|88364|0.981822|3600|0.040000|24801|564|K_|MPEGTS Stream ID|224 -video|1|95564|1.061822|91964|1.021822|3600|0.040000|16429|25944|__MPEGTS Stream ID|224 +video|1|95564|1.061822|91964|1.021822|3600|0.040000|16429|25944|__|MPEGTS Stream ID|224 -video|1|99164|1.101822|95564|1.061822|3600|0.040000|14508|42864|__MPEGTS Stream ID|224 +video|1|99164|1.101822|95564|1.061822|3600|0.040000|14508|42864|__|MPEGTS Stream ID|224 -video|1|102764|1.141822|99164|1.101822|3600|0.040000|12622|58092|__MPEGTS Stream ID|224 +video|1|102764|1.141822|99164|1.101822|3600|0.040000|12622|58092|__|MPEGTS Stream ID|224 -video|1|106364|1.181822|102764|1.141822|3600|0.040000|13393|71064|__MPEGTS Stream ID|224 +video|1|106364|1.181822|102764|1.141822|3600|0.040000|13393|71064|__|MPEGTS Stream ID|224 -video|1|109964|1.221822|106364|1.181822|3600|0.040000|13092|84788|__MPEGTS Stream ID|224 +video|1|109964|1.221822|106364|1.181822|3600|0.040000|13092|84788|__|MPEGTS Stream ID|224 -video|1|113564|1.261822|109964|1.221822|3600|0.040000|12755|98700|__MPEGTS Stream ID|224 +video|1|113564|1.261822|109964|1.221822|3600|0.040000|12755|98700|__|MPEGTS Stream ID|224 -video|1|117164|1.301822|113564|1.261822|3600|0.040000|12023|111860|__MPEGTS Stream ID|224 +video|1|117164|1.301822|113564|1.261822|3600|0.040000|12023|111860|__|MPEGTS Stream ID|224 -audio|0|90982|1.010911|90982|1.010911|2351|0.026122|208|152844|K_MPEGTS Stream ID|192 +audio|0|90982|1.010911|90982|1.010911|2351|0.026122|208|152844|K_|MPEGTS Stream ID|192 audio|0|93333|1.037033|93333|1.037033|2351|0.026122|209|N/A|K_ audio|0|95684|1.063156|95684|1.063156|2351|0.026122|209|N/A|K_ @@ -120,27 +120,27 @@ audio|0|114492|1.272133|114492|1.272133|2351|0.026122|209|N/A|K_ audio|0|116843|1.298256|116843|1.298256|2351|0.026122|209|N/A|K_ audio|0|119194|1.324378|119194|1.324378|2351|0.026122|209|N/A|K_ audio|0|121545|1.350500|121545|1.350500|2351|0.026122|209|N/A|K_ -video|1|120764|1.341822|117164|1.301822|3600|0.040000|14098|124268|__MPEGTS Stream ID|224 +video|1|120764|1.341822|117164|1.301822|3600|0.040000|14098|124268|__|MPEGTS Stream ID|224 -video|1|124364|1.381822|120764|1.341822|3600|0.040000|13329|139120|__MPEGTS Stream ID|224 +video|1|124364|1.381822|120764|1.341822|3600|0.040000|13329|139120|__|MPEGTS Stream ID|224 -video|1|127964|1.421822|124364|1.381822|3600|0.040000|12135|155852|__MPEGTS Stream ID|224 +video|1|127964|1.421822|124364|1.381822|3600|0.040000|12135|155852|__|MPEGTS Stream ID|224 -video|1|131564|1.461822|127964|1.421822|3600|0.040000|12282|168448|__MPEGTS Stream ID|224 +video|1|131564|1.461822|127964|1.421822|3600|0.040000|12282|168448|__|MPEGTS Stream ID|224 -video|1|135164|1.501822|131564|1.461822|3600|0.040000|24786|181420|K_MPEGTS Stream ID|224 +video|1|135164|1.501822|131564|1.461822|3600|0.040000|24786|181420|K_|MPEGTS Stream ID|224 -video|1|138764|1.541822|135164|1.501822|3600|0.040000|17440|206988|__MPEGTS Stream ID|224 +video|1|138764|1.541822|135164|1.501822|3600|0.040000|17440|206988|__|MPEGTS Stream ID|224 -video|1|142364|1.581822|138764|1.541822|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 +video|1|142364|1.581822|138764|1.541822|3600|0.040000|15019|224848|__|MPEGTS Stream ID|224 -video|1|145964|1.621822|142364|1.581822|3600|0.040000|13449|240640|__MPEGTS Stream ID|224 +video|1|145964|1.621822|142364|1.581822|3600|0.040000|13449|240640|__|MPEGTS Stream ID|224 -video|1|149564|1.661822|145964|1.621822|3600|0.040000|12398|254552|__MPEGTS Stream ID|224 +video|1|149564|1.661822|145964|1.621822|3600|0.040000|12398|254552|__|MPEGTS Stream ID|224 -video|1|153164|1.701822|149564|1.661822|3600|0.040000|13455|267336|__MPEGTS Stream ID|224 +video|1|153164|1.701822|149564|1.661822|3600|0.040000|13455|267336|__|MPEGTS Stream ID|224 -audio|0|123897|1.376633|123897|1.376633|2351|0.026122|209|308508|K_MPEGTS Stream ID|192 +audio|0|123897|1.376633|123897|1.376633|2351|0.026122|209|308508|K_|MPEGTS Stream ID|192 audio|0|126248|1.402756|126248|1.402756|2351|0.026122|209|N/A|K_ audio|0|128599|1.428878|128599|1.428878|2351|0.026122|209|N/A|K_ @@ -155,17 +155,17 @@ audio|0|147407|1.637856|147407|1.637856|2351|0.026122|209|N/A|K_ audio|0|149758|1.663978|149758|1.663978|2351|0.026122|209|N/A|K_ audio|0|152109|1.690100|152109|1.690100|2351|0.026122|209|N/A|K_ audio|0|154460|1.716222|154460|1.716222|2351|0.026122|209|N/A|K_ -video|1|156764|1.741822|153164|1.701822|3600|0.040000|13836|281624|__MPEGTS Stream ID|224 +video|1|156764|1.741822|153164|1.701822|3600|0.040000|13836|281624|__|MPEGTS Stream ID|224 -video|1|160364|1.781822|156764|1.741822|3600|0.040000|12163|295912|__MPEGTS Stream ID|224 +video|1|160364|1.781822|156764|1.741822|3600|0.040000|12163|295912|__|MPEGTS Stream ID|224 -video|1|163964|1.821822|160364|1.781822|3600|0.040000|12692|311516|__MPEGTS Stream ID|224 +video|1|163964|1.821822|160364|1.781822|3600|0.040000|12692|311516|__|MPEGTS Stream ID|224 -video|1|167564|1.861822|163964|1.821822|3600|0.040000|10824|325052|__MPEGTS Stream ID|224 +video|1|167564|1.861822|163964|1.821822|3600|0.040000|10824|325052|__|MPEGTS Stream ID|224 -video|1|171164|1.901822|167564|1.861822|3600|0.040000|11286|336144|__MPEGTS Stream ID|224 +video|1|171164|1.901822|167564|1.861822|3600|0.040000|11286|336144|__|MPEGTS Stream ID|224 -audio|0|156811|1.742344|156811|1.742344|2351|0.026122|209|386716|K_MPEGTS Stream ID|192 +audio|0|156811|1.742344|156811|1.742344|2351|0.026122|209|386716|K_|MPEGTS Stream ID|192 audio|0|159162|1.768467|159162|1.768467|2351|0.026122|209|N/A|K_ audio|0|161513|1.794589|161513|1.794589|2351|0.026122|209|N/A|K_ @@ -177,16 +177,16 @@ audio|0|173268|1.925200|173268|1.925200|2351|0.026122|209|N/A|K_ audio|0|175619|1.951322|175619|1.951322|2351|0.026122|209|N/A|K_ audio|0|177970|1.977444|177970|1.977444|2351|0.026122|209|N/A|K_ audio|0|180321|2.003567|180321|2.003567|2351|0.026122|209|N/A|K_ -video|1|174764|1.941822|171164|1.901822|3600|0.040000|12678|347800|__MPEGTS Stream ID|224 +video|1|174764|1.941822|171164|1.901822|3600|0.040000|12678|347800|__|MPEGTS Stream ID|224 video|1|178364|1.981822|174764|1.941822|3600|0.040000|24711|361336|K_ -video|1|139582|1.550911|135982|1.510911|3600|0.040000|12692|311516|__MPEGTS Stream ID|224 +video|1|139582|1.550911|135982|1.510911|3600|0.040000|12692|311516|__|MPEGTS Stream ID|224 -video|1|143182|1.590911|139582|1.550911|3600|0.040000|10824|325052|__MPEGTS Stream ID|224 +video|1|143182|1.590911|139582|1.550911|3600|0.040000|10824|325052|__|MPEGTS Stream ID|224 -video|1|146782|1.630911|143182|1.590911|3600|0.040000|11286|336144|__MPEGTS Stream ID|224 +video|1|146782|1.630911|143182|1.590911|3600|0.040000|11286|336144|__|MPEGTS Stream ID|224 -audio|0|132429|1.471433|132429|1.471433|2351|0.026122|209|386716|K_MPEGTS Stream ID|192 +audio|0|132429|1.471433|132429|1.471433|2351|0.026122|209|386716|K_|MPEGTS Stream ID|192 audio|0|134780|1.497556|134780|1.497556|2351|0.026122|209|N/A|K_ audio|0|137131|1.523678|137131|1.523678|2351|0.026122|209|N/A|K_ @@ -198,19 +198,18 @@ audio|0|148886|1.654289|148886|1.654289|2351|0.026122|209|N/A|K_ audio|0|151237|1.680411|151237|1.680411|2351|0.026122|209|N/A|K_ audio|0|153588|1.706533|153588|1.706533|2351|0.026122|209|N/A|K_ audio|0|155939|1.732656|155939|1.732656|2351|0.026122|209|N/A|K_ -video|1|150382|1.670911|146782|1.630911|3600|0.040000|12678|347800|__MPEGTS Stream ID|224 +video|1|150382|1.670911|146782|1.630911|3600|0.040000|12678|347800|__|MPEGTS Stream ID|224 video|1|153982|1.710911|150382|1.670911|3600|0.040000|24711|361336|K_ -video|1|161182|1.790911|157582|1.750911|3600|0.040000|12135|155852|__MPEGTS Stream ID|224 +video|1|161182|1.790911|157582|1.750911|3600|0.040000|12135|155852|__|MPEGTS Stream ID|224 -video|1|164782|1.830911|161182|1.790911|3600|0.040000|12282|168448|__MPEGTS Stream ID|224 +video|1|164782|1.830911|161182|1.790911|3600|0.040000|12282|168448|__|MPEGTS Stream ID|224 -video|1|168382|1.870911|164782|1.830911|3600|0.040000|24786|181420|K_MPEGTS Stream ID|224 +video|1|168382|1.870911|164782|1.830911|3600|0.040000|24786|181420|K_|MPEGTS Stream ID|224 -video|1|171982|1.910911|168382|1.870911|3600|0.040000|17440|206988|__MPEGTS Stream ID|224 +video|1|171982|1.910911|168382|1.870911|3600|0.040000|17440|206988|__|MPEGTS Stream ID|224 -video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 +video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__|MPEGTS Stream ID|224 0|mp2|unknown|audio|[3][0][0][0]|0x0003|s16p|44100|1|mono|0|N/A|0/0|0/0|1/90000|0|0.000000|N/A|N/A|64000|N/A|N/A|N/A|N/A|89|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 0 -1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1 -CPB properties|0|0|0|49152|-1 +1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1|CPB properties|0|0|0|49152|-1 diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux index fffc1c38c4..a7c98d3d76 100644 --- a/tests/ref/fate/flv-demux +++ b/tests/ref/fate/flv-demux @@ -1,6 +1,6 @@ -packet|codec_type=audio|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=46|duration_time=0.046000|size=9|pos=3241|flags=K_side_data|side_data_type=New Extradata +packet|codec_type=audio|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=46|duration_time=0.046000|size=9|pos=3241|flags=K_|side_data|side_data_type=New Extradata |data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=33|duration_time=0.033000|size=135|pos=3267|flags=K_side_data|side_data_type=New Extradata +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=33|duration_time=0.033000|size=135|pos=3267|flags=K_|side_data|side_data_type=New Extradata |data_hash=CRC32:3f2ccc9e packet|codec_type=video|stream_index=0|pts=33|pts_time=0.033000|dts=33|dts_time=0.033000|duration=33|duration_time=0.033000|size=92|pos=3422|flags=__|data_hash=CRC32:c14e72b2 packet|codec_type=audio|stream_index=1|pts=46|pts_time=0.046000|dts=46|dts_time=0.046000|duration=46|duration_time=0.046000|size=9|pos=3534|flags=K_|data_hash=CRC32:bbb61b93 diff --git a/tests/ref/fate/gapless-mp3-side-data b/tests/ref/fate/gapless-mp3-side-data index f0cfbd4c8c..59907f8ca4 100644 --- a/tests/ref/fate/gapless-mp3-side-data +++ b/tests/ref/fate/gapless-mp3-side-data @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=368640|duration_time=0.026122|size=417|pos=1451|flags=K_side_data|side_data_type=Skip Samples|skip_samples=1105|discard_padding=0|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=368640|duration_time=0.026122|size=417|pos=1451|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=1105|discard_padding=0|skip_reason=0|discard_reason=0 |data_hash=CRC32:ae0a5066 packet|codec_type=audio|stream_index=0|pts=368640|pts_time=0.026122|dts=368640|dts_time=0.026122|duration=368640|duration_time=0.026122|size=418|pos=1868|flags=K_|data_hash=CRC32:dbb7aa6c packet|codec_type=audio|stream_index=0|pts=737280|pts_time=0.052245|dts=737280|dts_time=0.052245|duration=368640|duration_time=0.026122|size=418|pos=2286|flags=K_|data_hash=CRC32:5fe9fd6b @@ -592,9 +592,9 @@ packet|codec_type=audio|stream_index=0|pts=217128960|pts_time=15.386122|dts=2171 packet|codec_type=audio|stream_index=0|pts=217497600|pts_time=15.412245|dts=217497600|dts_time=15.412245|duration=368640|duration_time=0.026122|size=418|pos=248046|flags=K_|data_hash=CRC32:dc78174d packet|codec_type=audio|stream_index=0|pts=217866240|pts_time=15.438367|dts=217866240|dts_time=15.438367|duration=368640|duration_time=0.026122|size=418|pos=248464|flags=K_|data_hash=CRC32:0b948a05 packet|codec_type=audio|stream_index=0|pts=218234880|pts_time=15.464490|dts=218234880|dts_time=15.464490|duration=368640|duration_time=0.026122|size=418|pos=248882|flags=K_|data_hash=CRC32:fbc83c3c -packet|codec_type=audio|stream_index=0|pts=218603520|pts_time=15.490612|dts=218603520|dts_time=15.490612|duration=368640|duration_time=0.026122|size=418|pos=249300|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=303|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=218603520|pts_time=15.490612|dts=218603520|dts_time=15.490612|duration=368640|duration_time=0.026122|size=418|pos=249300|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=303|skip_reason=0|discard_reason=0 |data_hash=CRC32:d5fb5f9c -packet|codec_type=audio|stream_index=0|pts=218972160|pts_time=15.516735|dts=218972160|dts_time=15.516735|duration=368640|duration_time=0.026122|size=418|pos=249718|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=1152|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=218972160|pts_time=15.516735|dts=218972160|dts_time=15.516735|duration=368640|duration_time=0.026122|size=418|pos=249718|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=1152|skip_reason=0|discard_reason=0 |data_hash=CRC32:3789f3cf stream|index=0|codec_name=mp3|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=44100|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/14112000|start_pts=353600|start_time=0.025057|duration_ts=219340800|duration=15.542857|bit_rate=128000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=595|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:encoder=LAME3.93 format|filename=gapless.mp3|nb_streams=1|nb_programs=0|format_name=mp3|start_time=0.025057|duration=15.542857|size=250264|bit_rate=128812|probe_score=51|tag:title=test diff --git a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac index 9b97b61aca..f967ac05bc 100644 --- a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac +++ b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac @@ -7,7 +7,7 @@ duration_ts=103326 start_time=0.000000 duration=2.344000 [/FORMAT] -packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data| +packet|pts=-1024|dts=-1024|duration=1024|flags=KD|side_data| packet|pts=0|dts=0|duration=1024|flags=K_ packet|pts=1024|dts=1024|duration=1024|flags=K_ diff --git a/tests/ref/fate/gaplessenc-pcm-to-mov-aac b/tests/ref/fate/gaplessenc-pcm-to-mov-aac index 43d13f5bc8..82bed6f936 100644 --- a/tests/ref/fate/gaplessenc-pcm-to-mov-aac +++ b/tests/ref/fate/gaplessenc-pcm-to-mov-aac @@ -7,7 +7,7 @@ duration_ts=529200 start_time=0.000000 duration=12.000000 [/FORMAT] -packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data| +packet|pts=-1024|dts=-1024|duration=1024|flags=KD|side_data| packet|pts=0|dts=0|duration=1024|flags=K_ packet|pts=1024|dts=1024|duration=1024|flags=K_ diff --git a/tests/ref/fate/gaplessinfo-itunes1 b/tests/ref/fate/gaplessinfo-itunes1 index 4944c78e3b..841bdb31d0 100644 --- a/tests/ref/fate/gaplessinfo-itunes1 +++ b/tests/ref/fate/gaplessinfo-itunes1 @@ -7,7 +7,7 @@ duration_ts=1294336 start_time=0.047889 duration=29.350023 [/FORMAT] -packet|pts=0|dts=0|duration=1024|flags=K_side_data| +packet|pts=0|dts=0|duration=1024|flags=K_|side_data| packet|pts=1024|dts=1024|duration=1024|flags=K_ packet|pts=2048|dts=2048|duration=1024|flags=K_ diff --git a/tests/ref/fate/gaplessinfo-itunes2 b/tests/ref/fate/gaplessinfo-itunes2 index cf6825d13c..3184a5ea59 100644 --- a/tests/ref/fate/gaplessinfo-itunes2 +++ b/tests/ref/fate/gaplessinfo-itunes2 @@ -7,7 +7,7 @@ duration_ts=105472 start_time=0.047891 duration=2.391655 [/FORMAT] -packet|pts=0|dts=0|duration=1024|flags=K_side_data| +packet|pts=0|dts=0|duration=1024|flags=K_|side_data| packet|pts=1024|dts=1024|duration=1024|flags=K_ packet|pts=2048|dts=2048|duration=1024|flags=K_ diff --git a/tests/ref/fate/mov-aac-2048-priming b/tests/ref/fate/mov-aac-2048-priming index 5c6361558b..071c3627f3 100644 --- a/tests/ref/fate/mov-aac-2048-priming +++ b/tests/ref/fate/mov-aac-2048-priming @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=-2048|pts_time=-0.046440|dts=-2048|dts_time=-0.046440|duration=1024|duration_time=0.023220|size=258|pos=36|flags=KDside_data|side_data_type=Skip Samples|skip_samples=2048|discard_padding=0|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=-2048|pts_time=-0.046440|dts=-2048|dts_time=-0.046440|duration=1024|duration_time=0.023220|size=258|pos=36|flags=KD|side_data|side_data_type=Skip Samples|skip_samples=2048|discard_padding=0|skip_reason=0|discard_reason=0 packet|codec_type=audio|stream_index=0|pts=-1024|pts_time=-0.023220|dts=-1024|dts_time=-0.023220|duration=1024|duration_time=0.023220|size=258|pos=294|flags=KD packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=146|pos=552|flags=K_ diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie index 2963de529d..798f47ab84 100644 --- a/tests/ref/fate/mov-zombie +++ b/tests/ref/fate/mov-zombie @@ -1,198 +1,197 @@ packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-3004|dts_time=-0.033378|duration=3003|duration_time=0.033367|size=4133|pos=11309|flags=K_ packet|codec_type=video|stream_index=0|pts=5440|pts_time=0.060444|dts=-567|dts_time=-0.006300|duration=3003|duration_time=0.033367|size=1077|pos=15442|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=2437|pts_time=0.027078|dts=2436|dts_time=0.027067|duration=3003|duration_time=0.033367|size=355|pos=16519|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=2437|pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=2437|pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=11446|pts_time=0.127178|dts=5439|dts_time=0.060433|duration=3003|duration_time=0.033367|size=1110|pos=16874|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=5440|pts_time=0.060444|pkt_dts=5439|pkt_dts_time=0.060433|best_effort_timestamp=5440|best_effort_timestamp_time=0.060444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=1|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=5440|pts_time=0.060444|pkt_dts=5439|pkt_dts_time=0.060433|best_effort_timestamp=5440|best_effort_timestamp_time=0.060444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=1|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=8443|pts_time=0.093811|dts=8442|dts_time=0.093800|duration=3003|duration_time=0.033367|size=430|pos=17984|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=8443|pts_time=0.093811|pkt_dts=8442|pkt_dts_time=0.093800|best_effort_timestamp=8443|best_effort_timestamp_time=0.093811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=4|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=8443|pts_time=0.093811|pkt_dts=8442|pkt_dts_time=0.093800|best_effort_timestamp=8443|best_effort_timestamp_time=0.093811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=4|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=17452|pts_time=0.193911|dts=11445|dts_time=0.127167|duration=3003|duration_time=0.033367|size=1485|pos=18414|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=11446|pts_time=0.127178|pkt_dts=11445|pkt_dts_time=0.127167|best_effort_timestamp=11446|best_effort_timestamp_time=0.127178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=3|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=11446|pts_time=0.127178|pkt_dts=11445|pkt_dts_time=0.127167|best_effort_timestamp=11446|best_effort_timestamp_time=0.127178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=3|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=14449|pts_time=0.160544|dts=14448|dts_time=0.160533|duration=3003|duration_time=0.033367|size=1005|pos=19899|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=14449|pts_time=0.160544|pkt_dts=14448|pkt_dts_time=0.160533|best_effort_timestamp=14449|best_effort_timestamp_time=0.160544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=6|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=14449|pts_time=0.160544|pkt_dts=14448|pkt_dts_time=0.160533|best_effort_timestamp=14449|best_effort_timestamp_time=0.160544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=6|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=23458|pts_time=0.260644|dts=17451|dts_time=0.193900|duration=3003|duration_time=0.033367|size=1976|pos=20904|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=17452|pts_time=0.193911|pkt_dts=17451|pkt_dts_time=0.193900|best_effort_timestamp=17452|best_effort_timestamp_time=0.193911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=5|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=17452|pts_time=0.193911|pkt_dts=17451|pkt_dts_time=0.193900|best_effort_timestamp=17452|best_effort_timestamp_time=0.193911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=5|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=20455|pts_time=0.227278|dts=20454|dts_time=0.227267|duration=3003|duration_time=0.033367|size=904|pos=22880|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=20455|pts_time=0.227278|pkt_dts=20454|pkt_dts_time=0.227267|best_effort_timestamp=20455|best_effort_timestamp_time=0.227278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=8|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=20455|pts_time=0.227278|pkt_dts=20454|pkt_dts_time=0.227267|best_effort_timestamp=20455|best_effort_timestamp_time=0.227278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=8|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=29464|pts_time=0.327378|dts=23457|dts_time=0.260633|duration=3003|duration_time=0.033367|size=1254|pos=23784|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=23458|pts_time=0.260644|pkt_dts=23457|pkt_dts_time=0.260633|best_effort_timestamp=23458|best_effort_timestamp_time=0.260644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=7|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=23458|pts_time=0.260644|pkt_dts=23457|pkt_dts_time=0.260633|best_effort_timestamp=23458|best_effort_timestamp_time=0.260644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=7|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=26461|pts_time=0.294011|dts=26460|dts_time=0.294000|duration=3003|duration_time=0.033367|size=700|pos=25038|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=26461|pts_time=0.294011|pkt_dts=26460|pkt_dts_time=0.294000|best_effort_timestamp=26461|best_effort_timestamp_time=0.294011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=10|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=26461|pts_time=0.294011|pkt_dts=26460|pkt_dts_time=0.294000|best_effort_timestamp=26461|best_effort_timestamp_time=0.294011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=10|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=35470|pts_time=0.394111|dts=29463|dts_time=0.327367|duration=3003|duration_time=0.033367|size=1311|pos=25738|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=29464|pts_time=0.327378|pkt_dts=29463|pkt_dts_time=0.327367|best_effort_timestamp=29464|best_effort_timestamp_time=0.327378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=9|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=29464|pts_time=0.327378|pkt_dts=29463|pkt_dts_time=0.327367|best_effort_timestamp=29464|best_effort_timestamp_time=0.327378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=9|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=32467|pts_time=0.360744|dts=32466|dts_time=0.360733|duration=3003|duration_time=0.033367|size=631|pos=27049|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=32467|pts_time=0.360744|pkt_dts=32466|pkt_dts_time=0.360733|best_effort_timestamp=32467|best_effort_timestamp_time=0.360744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=12|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=32467|pts_time=0.360744|pkt_dts=32466|pkt_dts_time=0.360733|best_effort_timestamp=32467|best_effort_timestamp_time=0.360744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=12|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=41476|pts_time=0.460844|dts=35469|dts_time=0.394100|duration=3003|duration_time=0.033367|size=1296|pos=27680|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=35470|pts_time=0.394111|pkt_dts=35469|pkt_dts_time=0.394100|best_effort_timestamp=35470|best_effort_timestamp_time=0.394111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=11|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=35470|pts_time=0.394111|pkt_dts=35469|pkt_dts_time=0.394100|best_effort_timestamp=35470|best_effort_timestamp_time=0.394111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=11|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=38473|pts_time=0.427478|dts=38472|dts_time=0.427467|duration=3003|duration_time=0.033367|size=466|pos=28976|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=38473|pts_time=0.427478|pkt_dts=38472|pkt_dts_time=0.427467|best_effort_timestamp=38473|best_effort_timestamp_time=0.427478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=14|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=38473|pts_time=0.427478|pkt_dts=38472|pkt_dts_time=0.427467|best_effort_timestamp=38473|best_effort_timestamp_time=0.427478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=14|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=47482|pts_time=0.527578|dts=41475|dts_time=0.460833|duration=3003|duration_time=0.033367|size=1638|pos=29442|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=41476|pts_time=0.460844|pkt_dts=41475|pkt_dts_time=0.460833|best_effort_timestamp=41476|best_effort_timestamp_time=0.460844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=13|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=41476|pts_time=0.460844|pkt_dts=41475|pkt_dts_time=0.460833|best_effort_timestamp=41476|best_effort_timestamp_time=0.460844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=13|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=44479|pts_time=0.494211|dts=44478|dts_time=0.494200|duration=3003|duration_time=0.033367|size=907|pos=31080|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=44479|pts_time=0.494211|pkt_dts=44478|pkt_dts_time=0.494200|best_effort_timestamp=44479|best_effort_timestamp_time=0.494211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=16|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=44479|pts_time=0.494211|pkt_dts=44478|pkt_dts_time=0.494200|best_effort_timestamp=44479|best_effort_timestamp_time=0.494211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=16|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=53488|pts_time=0.594311|dts=47481|dts_time=0.527567|duration=3003|duration_time=0.033367|size=1362|pos=31987|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=47482|pts_time=0.527578|pkt_dts=47481|pkt_dts_time=0.527567|best_effort_timestamp=47482|best_effort_timestamp_time=0.527578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=15|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=47482|pts_time=0.527578|pkt_dts=47481|pkt_dts_time=0.527567|best_effort_timestamp=47482|best_effort_timestamp_time=0.527578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=15|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=50485|pts_time=0.560944|dts=50484|dts_time=0.560933|duration=3003|duration_time=0.033367|size=682|pos=33349|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=50485|pts_time=0.560944|pkt_dts=50484|pkt_dts_time=0.560933|best_effort_timestamp=50485|best_effort_timestamp_time=0.560944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=18|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=50485|pts_time=0.560944|pkt_dts=50484|pkt_dts_time=0.560933|best_effort_timestamp=50485|best_effort_timestamp_time=0.560944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=18|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=59494|pts_time=0.661044|dts=53487|dts_time=0.594300|duration=3003|duration_time=0.033367|size=2917|pos=34031|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=53488|pts_time=0.594311|pkt_dts=53487|pkt_dts_time=0.594300|best_effort_timestamp=53488|best_effort_timestamp_time=0.594311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=17|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=53488|pts_time=0.594311|pkt_dts=53487|pkt_dts_time=0.594300|best_effort_timestamp=53488|best_effort_timestamp_time=0.594311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=17|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=56491|pts_time=0.627678|dts=56490|dts_time=0.627667|duration=3003|duration_time=0.033367|size=1174|pos=36948|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=56491|pts_time=0.627678|pkt_dts=56490|pkt_dts_time=0.627667|best_effort_timestamp=56491|best_effort_timestamp_time=0.627678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=20|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=56491|pts_time=0.627678|pkt_dts=56490|pkt_dts_time=0.627667|best_effort_timestamp=56491|best_effort_timestamp_time=0.627678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=20|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=65500|pts_time=0.727778|dts=59493|dts_time=0.661033|duration=3003|duration_time=0.033367|size=1748|pos=38122|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=59494|pts_time=0.661044|pkt_dts=59493|pkt_dts_time=0.661033|best_effort_timestamp=59494|best_effort_timestamp_time=0.661044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=19|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=59494|pts_time=0.661044|pkt_dts=59493|pkt_dts_time=0.661033|best_effort_timestamp=59494|best_effort_timestamp_time=0.661044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=19|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=62497|pts_time=0.694411|dts=62496|dts_time=0.694400|duration=3003|duration_time=0.033367|size=926|pos=39870|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=62497|pts_time=0.694411|pkt_dts=62496|pkt_dts_time=0.694400|best_effort_timestamp=62497|best_effort_timestamp_time=0.694411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=22|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=62497|pts_time=0.694411|pkt_dts=62496|pkt_dts_time=0.694400|best_effort_timestamp=62497|best_effort_timestamp_time=0.694411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=22|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=68503|pts_time=0.761144|dts=65499|dts_time=0.727767|duration=3003|duration_time=0.033367|size=918|pos=40796|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=65500|pts_time=0.727778|pkt_dts=65499|pkt_dts_time=0.727767|best_effort_timestamp=65500|best_effort_timestamp_time=0.727778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=21|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=65500|pts_time=0.727778|pkt_dts=65499|pkt_dts_time=0.727767|best_effort_timestamp=65500|best_effort_timestamp_time=0.727778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=21|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=71506|pts_time=0.794511|dts=68502|dts_time=0.761133|duration=3003|duration_time=0.033367|size=3846|pos=41714|flags=K_ -frame|media_type=video|stream_index=0|key_frame=0|pts=68503|pts_time=0.761144|pkt_dts=68502|pkt_dts_time=0.761133|best_effort_timestamp=68503|best_effort_timestamp_time=0.761144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=23|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=68503|pts_time=0.761144|pkt_dts=68502|pkt_dts_time=0.761133|best_effort_timestamp=68503|best_effort_timestamp_time=0.761144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=23|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=77512|pts_time=0.861244|dts=71505|dts_time=0.794500|duration=3003|duration_time=0.033367|size=1932|pos=45560|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pts=71506|pts_time=0.794511|pkt_dts=71505|pkt_dts_time=0.794500|best_effort_timestamp=71506|best_effort_timestamp_time=0.794511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=24|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=1|pts=71506|pts_time=0.794511|pkt_dts=71505|pkt_dts_time=0.794500|best_effort_timestamp=71506|best_effort_timestamp_time=0.794511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=24|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=74509|pts_time=0.827878|dts=74508|dts_time=0.827867|duration=3003|duration_time=0.033367|size=1159|pos=47492|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=74509|pts_time=0.827878|pkt_dts=74508|pkt_dts_time=0.827867|best_effort_timestamp=74509|best_effort_timestamp_time=0.827878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=26|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=74509|pts_time=0.827878|pkt_dts=74508|pkt_dts_time=0.827867|best_effort_timestamp=74509|best_effort_timestamp_time=0.827878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=26|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=83518|pts_time=0.927978|dts=77511|dts_time=0.861233|duration=3003|duration_time=0.033367|size=1522|pos=48651|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=77512|pts_time=0.861244|pkt_dts=77511|pkt_dts_time=0.861233|best_effort_timestamp=77512|best_effort_timestamp_time=0.861244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=25|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=77512|pts_time=0.861244|pkt_dts=77511|pkt_dts_time=0.861233|best_effort_timestamp=77512|best_effort_timestamp_time=0.861244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=25|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=80515|pts_time=0.894611|dts=80514|dts_time=0.894600|duration=3003|duration_time=0.033367|size=719|pos=50173|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=80515|pts_time=0.894611|pkt_dts=80514|pkt_dts_time=0.894600|best_effort_timestamp=80515|best_effort_timestamp_time=0.894611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=28|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=80515|pts_time=0.894611|pkt_dts=80514|pkt_dts_time=0.894600|best_effort_timestamp=80515|best_effort_timestamp_time=0.894611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=28|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=89524|pts_time=0.994711|dts=83517|dts_time=0.927967|duration=3003|duration_time=0.033367|size=1700|pos=50892|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=83518|pts_time=0.927978|pkt_dts=83517|pkt_dts_time=0.927967|best_effort_timestamp=83518|best_effort_timestamp_time=0.927978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=27|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=83518|pts_time=0.927978|pkt_dts=83517|pkt_dts_time=0.927967|best_effort_timestamp=83518|best_effort_timestamp_time=0.927978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=27|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=86521|pts_time=0.961344|dts=86520|dts_time=0.961333|duration=3003|duration_time=0.033367|size=1099|pos=52592|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=86521|pts_time=0.961344|pkt_dts=86520|pkt_dts_time=0.961333|best_effort_timestamp=86521|best_effort_timestamp_time=0.961344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=30|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=86521|pts_time=0.961344|pkt_dts=86520|pkt_dts_time=0.961333|best_effort_timestamp=86521|best_effort_timestamp_time=0.961344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=30|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=95530|pts_time=1.061444|dts=89523|dts_time=0.994700|duration=3003|duration_time=0.033367|size=2558|pos=53691|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=89524|pts_time=0.994711|pkt_dts=89523|pkt_dts_time=0.994700|best_effort_timestamp=89524|best_effort_timestamp_time=0.994711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=29|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=89524|pts_time=0.994711|pkt_dts=89523|pkt_dts_time=0.994700|best_effort_timestamp=89524|best_effort_timestamp_time=0.994711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=29|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=92527|pts_time=1.028078|dts=92526|dts_time=1.028067|duration=3003|duration_time=0.033367|size=1008|pos=56249|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=92527|pts_time=1.028078|pkt_dts=92526|pkt_dts_time=1.028067|best_effort_timestamp=92527|best_effort_timestamp_time=1.028078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=32|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=92527|pts_time=1.028078|pkt_dts=92526|pkt_dts_time=1.028067|best_effort_timestamp=92527|best_effort_timestamp_time=1.028078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=32|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=101536|pts_time=1.128178|dts=95529|dts_time=1.061433|duration=3003|duration_time=0.033367|size=1236|pos=57257|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=95530|pts_time=1.061444|pkt_dts=95529|pkt_dts_time=1.061433|best_effort_timestamp=95530|best_effort_timestamp_time=1.061444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=31|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=95530|pts_time=1.061444|pkt_dts=95529|pkt_dts_time=1.061433|best_effort_timestamp=95530|best_effort_timestamp_time=1.061444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=31|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=98533|pts_time=1.094811|dts=98532|dts_time=1.094800|duration=3003|duration_time=0.033367|size=607|pos=58493|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=98533|pts_time=1.094811|pkt_dts=98532|pkt_dts_time=1.094800|best_effort_timestamp=98533|best_effort_timestamp_time=1.094811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=34|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=98533|pts_time=1.094811|pkt_dts=98532|pkt_dts_time=1.094800|best_effort_timestamp=98533|best_effort_timestamp_time=1.094811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=34|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=107542|pts_time=1.194911|dts=101535|dts_time=1.128167|duration=3003|duration_time=0.033367|size=1883|pos=59100|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=101536|pts_time=1.128178|pkt_dts=101535|pkt_dts_time=1.128167|best_effort_timestamp=101536|best_effort_timestamp_time=1.128178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=33|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=101536|pts_time=1.128178|pkt_dts=101535|pkt_dts_time=1.128167|best_effort_timestamp=101536|best_effort_timestamp_time=1.128178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=33|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=104539|pts_time=1.161544|dts=104538|dts_time=1.161533|duration=3003|duration_time=0.033367|size=893|pos=60983|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=104539|pts_time=1.161544|pkt_dts=104538|pkt_dts_time=1.161533|best_effort_timestamp=104539|best_effort_timestamp_time=1.161544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=36|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=104539|pts_time=1.161544|pkt_dts=104538|pkt_dts_time=1.161533|best_effort_timestamp=104539|best_effort_timestamp_time=1.161544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=36|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=113548|pts_time=1.261644|dts=107541|dts_time=1.194900|duration=3003|duration_time=0.033367|size=1305|pos=61876|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=107542|pts_time=1.194911|pkt_dts=107541|pkt_dts_time=1.194900|best_effort_timestamp=107542|best_effort_timestamp_time=1.194911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=35|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=107542|pts_time=1.194911|pkt_dts=107541|pkt_dts_time=1.194900|best_effort_timestamp=107542|best_effort_timestamp_time=1.194911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=35|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=110545|pts_time=1.228278|dts=110544|dts_time=1.228267|duration=3003|duration_time=0.033367|size=472|pos=63181|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=110545|pts_time=1.228278|pkt_dts=110544|pkt_dts_time=1.228267|best_effort_timestamp=110545|best_effort_timestamp_time=1.228278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=38|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=110545|pts_time=1.228278|pkt_dts=110544|pkt_dts_time=1.228267|best_effort_timestamp=110545|best_effort_timestamp_time=1.228278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=38|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=119554|pts_time=1.328378|dts=113547|dts_time=1.261633|duration=3003|duration_time=0.033367|size=1411|pos=63653|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=113548|pts_time=1.261644|pkt_dts=113547|pkt_dts_time=1.261633|best_effort_timestamp=113548|best_effort_timestamp_time=1.261644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=37|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=113548|pts_time=1.261644|pkt_dts=113547|pkt_dts_time=1.261633|best_effort_timestamp=113548|best_effort_timestamp_time=1.261644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=37|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=116551|pts_time=1.295011|dts=116550|dts_time=1.295000|duration=3003|duration_time=0.033367|size=616|pos=65064|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=116551|pts_time=1.295011|pkt_dts=116550|pkt_dts_time=1.295000|best_effort_timestamp=116551|best_effort_timestamp_time=1.295011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=40|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=116551|pts_time=1.295011|pkt_dts=116550|pkt_dts_time=1.295000|best_effort_timestamp=116551|best_effort_timestamp_time=1.295011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=40|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=125560|pts_time=1.395111|dts=119553|dts_time=1.328367|duration=3003|duration_time=0.033367|size=1291|pos=65680|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=119554|pts_time=1.328378|pkt_dts=119553|pkt_dts_time=1.328367|best_effort_timestamp=119554|best_effort_timestamp_time=1.328378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=39|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=119554|pts_time=1.328378|pkt_dts=119553|pkt_dts_time=1.328367|best_effort_timestamp=119554|best_effort_timestamp_time=1.328378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=39|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=122557|pts_time=1.361744|dts=122556|dts_time=1.361733|duration=3003|duration_time=0.033367|size=470|pos=66971|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=122557|pts_time=1.361744|pkt_dts=122556|pkt_dts_time=1.361733|best_effort_timestamp=122557|best_effort_timestamp_time=1.361744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=42|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=122557|pts_time=1.361744|pkt_dts=122556|pkt_dts_time=1.361733|best_effort_timestamp=122557|best_effort_timestamp_time=1.361744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=42|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=131566|pts_time=1.461844|dts=125559|dts_time=1.395100|duration=3003|duration_time=0.033367|size=1977|pos=67441|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=125560|pts_time=1.395111|pkt_dts=125559|pkt_dts_time=1.395100|best_effort_timestamp=125560|best_effort_timestamp_time=1.395111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=41|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=125560|pts_time=1.395111|pkt_dts=125559|pkt_dts_time=1.395100|best_effort_timestamp=125560|best_effort_timestamp_time=1.395111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=41|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=128563|pts_time=1.428478|dts=128562|dts_time=1.428467|duration=3003|duration_time=0.033367|size=436|pos=69418|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=128563|pts_time=1.428478|pkt_dts=128562|pkt_dts_time=1.428467|best_effort_timestamp=128563|best_effort_timestamp_time=1.428478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=44|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=128563|pts_time=1.428478|pkt_dts=128562|pkt_dts_time=1.428467|best_effort_timestamp=128563|best_effort_timestamp_time=1.428478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=44|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=137572|pts_time=1.528578|dts=131565|dts_time=1.461833|duration=3003|duration_time=0.033367|size=2566|pos=69854|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=131566|pts_time=1.461844|pkt_dts=131565|pkt_dts_time=1.461833|best_effort_timestamp=131566|best_effort_timestamp_time=1.461844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=43|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=131566|pts_time=1.461844|pkt_dts=131565|pkt_dts_time=1.461833|best_effort_timestamp=131566|best_effort_timestamp_time=1.461844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=43|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=134569|pts_time=1.495211|dts=134568|dts_time=1.495200|duration=3003|duration_time=0.033367|size=886|pos=72420|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=134569|pts_time=1.495211|pkt_dts=134568|pkt_dts_time=1.495200|best_effort_timestamp=134569|best_effort_timestamp_time=1.495211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=46|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=134569|pts_time=1.495211|pkt_dts=134568|pkt_dts_time=1.495200|best_effort_timestamp=134569|best_effort_timestamp_time=1.495211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=46|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=140575|pts_time=1.561944|dts=137571|dts_time=1.528567|duration=3003|duration_time=0.033367|size=1330|pos=73306|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=137572|pts_time=1.528578|pkt_dts=137571|pkt_dts_time=1.528567|best_effort_timestamp=137572|best_effort_timestamp_time=1.528578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=45|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=137572|pts_time=1.528578|pkt_dts=137571|pkt_dts_time=1.528567|best_effort_timestamp=137572|best_effort_timestamp_time=1.528578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=45|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=143578|pts_time=1.595311|dts=140574|dts_time=1.561933|duration=3003|duration_time=0.033367|size=2227|pos=74636|flags=K_ -frame|media_type=video|stream_index=0|key_frame=0|pts=140575|pts_time=1.561944|pkt_dts=140574|pkt_dts_time=1.561933|best_effort_timestamp=140575|best_effort_timestamp_time=1.561944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=47|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=140575|pts_time=1.561944|pkt_dts=140574|pkt_dts_time=1.561933|best_effort_timestamp=140575|best_effort_timestamp_time=1.561944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=47|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=149584|pts_time=1.662044|dts=143577|dts_time=1.595300|duration=3003|duration_time=0.033367|size=2210|pos=76863|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pts=143578|pts_time=1.595311|pkt_dts=143577|pkt_dts_time=1.595300|best_effort_timestamp=143578|best_effort_timestamp_time=1.595311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=48|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=1|pts=143578|pts_time=1.595311|pkt_dts=143577|pkt_dts_time=1.595300|best_effort_timestamp=143578|best_effort_timestamp_time=1.595311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=48|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=146581|pts_time=1.628678|dts=146580|dts_time=1.628667|duration=3003|duration_time=0.033367|size=1498|pos=79073|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=146581|pts_time=1.628678|pkt_dts=146580|pkt_dts_time=1.628667|best_effort_timestamp=146581|best_effort_timestamp_time=1.628678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=50|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=146581|pts_time=1.628678|pkt_dts=146580|pkt_dts_time=1.628667|best_effort_timestamp=146581|best_effort_timestamp_time=1.628678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=50|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=155590|pts_time=1.728778|dts=149583|dts_time=1.662033|duration=3003|duration_time=0.033367|size=1721|pos=80571|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=149584|pts_time=1.662044|pkt_dts=149583|pkt_dts_time=1.662033|best_effort_timestamp=149584|best_effort_timestamp_time=1.662044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=49|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=149584|pts_time=1.662044|pkt_dts=149583|pkt_dts_time=1.662033|best_effort_timestamp=149584|best_effort_timestamp_time=1.662044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=49|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=152587|pts_time=1.695411|dts=152586|dts_time=1.695400|duration=3003|duration_time=0.033367|size=1238|pos=82292|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=152587|pts_time=1.695411|pkt_dts=152586|pkt_dts_time=1.695400|best_effort_timestamp=152587|best_effort_timestamp_time=1.695411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=52|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=152587|pts_time=1.695411|pkt_dts=152586|pkt_dts_time=1.695400|best_effort_timestamp=152587|best_effort_timestamp_time=1.695411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=52|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=161596|pts_time=1.795511|dts=155589|dts_time=1.728767|duration=3003|duration_time=0.033367|size=1753|pos=83530|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=155590|pts_time=1.728778|pkt_dts=155589|pkt_dts_time=1.728767|best_effort_timestamp=155590|best_effort_timestamp_time=1.728778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=51|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=155590|pts_time=1.728778|pkt_dts=155589|pkt_dts_time=1.728767|best_effort_timestamp=155590|best_effort_timestamp_time=1.728778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=51|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=158593|pts_time=1.762144|dts=158592|dts_time=1.762133|duration=3003|duration_time=0.033367|size=1014|pos=85283|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=158593|pts_time=1.762144|pkt_dts=158592|pkt_dts_time=1.762133|best_effort_timestamp=158593|best_effort_timestamp_time=1.762144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=54|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=158593|pts_time=1.762144|pkt_dts=158592|pkt_dts_time=1.762133|best_effort_timestamp=158593|best_effort_timestamp_time=1.762144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=54|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=167602|pts_time=1.862244|dts=161595|dts_time=1.795500|duration=3003|duration_time=0.033367|size=2408|pos=86297|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=161596|pts_time=1.795511|pkt_dts=161595|pkt_dts_time=1.795500|best_effort_timestamp=161596|best_effort_timestamp_time=1.795511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=53|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=161596|pts_time=1.795511|pkt_dts=161595|pkt_dts_time=1.795500|best_effort_timestamp=161596|best_effort_timestamp_time=1.795511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=53|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=164599|pts_time=1.828878|dts=164598|dts_time=1.828867|duration=3003|duration_time=0.033367|size=1727|pos=88705|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=164599|pts_time=1.828878|pkt_dts=164598|pkt_dts_time=1.828867|best_effort_timestamp=164599|best_effort_timestamp_time=1.828878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=56|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=164599|pts_time=1.828878|pkt_dts=164598|pkt_dts_time=1.828867|best_effort_timestamp=164599|best_effort_timestamp_time=1.828878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=56|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=173608|pts_time=1.928978|dts=167601|dts_time=1.862233|duration=3003|duration_time=0.033367|size=1504|pos=90432|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=167602|pts_time=1.862244|pkt_dts=167601|pkt_dts_time=1.862233|best_effort_timestamp=167602|best_effort_timestamp_time=1.862244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=55|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=167602|pts_time=1.862244|pkt_dts=167601|pkt_dts_time=1.862233|best_effort_timestamp=167602|best_effort_timestamp_time=1.862244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=55|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=170605|pts_time=1.895611|dts=170604|dts_time=1.895600|duration=3003|duration_time=0.033367|size=957|pos=91936|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=170605|pts_time=1.895611|pkt_dts=170604|pkt_dts_time=1.895600|best_effort_timestamp=170605|best_effort_timestamp_time=1.895611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=58|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=170605|pts_time=1.895611|pkt_dts=170604|pkt_dts_time=1.895600|best_effort_timestamp=170605|best_effort_timestamp_time=1.895611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=58|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=179614|pts_time=1.995711|dts=173607|dts_time=1.928967|duration=3003|duration_time=0.033367|size=1890|pos=92893|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=173608|pts_time=1.928978|pkt_dts=173607|pkt_dts_time=1.928967|best_effort_timestamp=173608|best_effort_timestamp_time=1.928978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=57|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=173608|pts_time=1.928978|pkt_dts=173607|pkt_dts_time=1.928967|best_effort_timestamp=173608|best_effort_timestamp_time=1.928978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=57|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=176611|pts_time=1.962344|dts=176610|dts_time=1.962333|duration=3003|duration_time=0.033367|size=1239|pos=94783|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=176611|pts_time=1.962344|pkt_dts=176610|pkt_dts_time=1.962333|best_effort_timestamp=176611|best_effort_timestamp_time=1.962344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=60|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=176611|pts_time=1.962344|pkt_dts=176610|pkt_dts_time=1.962333|best_effort_timestamp=176611|best_effort_timestamp_time=1.962344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=60|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=185620|pts_time=2.062444|dts=179613|dts_time=1.995700|duration=3003|duration_time=0.033367|size=1856|pos=96022|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=179614|pts_time=1.995711|pkt_dts=179613|pkt_dts_time=1.995700|best_effort_timestamp=179614|best_effort_timestamp_time=1.995711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=59|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=179614|pts_time=1.995711|pkt_dts=179613|pkt_dts_time=1.995700|best_effort_timestamp=179614|best_effort_timestamp_time=1.995711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=59|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=182617|pts_time=2.029078|dts=182616|dts_time=2.029067|duration=3003|duration_time=0.033367|size=1302|pos=97878|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=182617|pts_time=2.029078|pkt_dts=182616|pkt_dts_time=2.029067|best_effort_timestamp=182617|best_effort_timestamp_time=2.029078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=62|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=182617|pts_time=2.029078|pkt_dts=182616|pkt_dts_time=2.029067|best_effort_timestamp=182617|best_effort_timestamp_time=2.029078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=62|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=191626|pts_time=2.129178|dts=185619|dts_time=2.062433|duration=3003|duration_time=0.033367|size=1666|pos=99180|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=185620|pts_time=2.062444|pkt_dts=185619|pkt_dts_time=2.062433|best_effort_timestamp=185620|best_effort_timestamp_time=2.062444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=61|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=185620|pts_time=2.062444|pkt_dts=185619|pkt_dts_time=2.062433|best_effort_timestamp=185620|best_effort_timestamp_time=2.062444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=61|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=188623|pts_time=2.095811|dts=188622|dts_time=2.095800|duration=3003|duration_time=0.033367|size=974|pos=100846|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=197632|pts_time=2.195911|dts=191625|dts_time=2.129167|duration=3003|duration_time=0.033367|size=580|pos=101820|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|extradata_size=34|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264 -side_data|side_data_type=Display Matrix|displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|rotation=0 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|extradata_size=34|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264|side_data|side_data_type=Display Matrix|displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|rotation=0 diff --git a/tests/ref/fate/oggopus-demux b/tests/ref/fate/oggopus-demux index ab5ba2a93b..7ea5dfe8a0 100644 --- a/tests/ref/fate/oggopus-demux +++ b/tests/ref/fate/oggopus-demux @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=-356|pts_time=-0.007417|dts=-356|dts_time=-0.007417|duration=960|duration_time=0.020000|size=402|pos=841|flags=K_side_data|side_data_type=Skip Samples|skip_samples=356|discard_padding=0|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=-356|pts_time=-0.007417|dts=-356|dts_time=-0.007417|duration=960|duration_time=0.020000|size=402|pos=841|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=356|discard_padding=0|skip_reason=0|discard_reason=0 |data_hash=CRC32:052ff811 packet|codec_type=audio|stream_index=0|pts=604|pts_time=0.012583|dts=604|dts_time=0.012583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:77f232d3 packet|codec_type=audio|stream_index=0|pts=1564|pts_time=0.032583|dts=1564|dts_time=0.032583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K_|data_hash=CRC32:3746e223 @@ -39,7 +39,7 @@ packet|codec_type=audio|stream_index=0|pts=34204|pts_time=0.712583|dts=34204|dts packet|codec_type=audio|stream_index=0|pts=35164|pts_time=0.732583|dts=35164|dts_time=0.732583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K_|data_hash=CRC32:aba60587 packet|codec_type=audio|stream_index=0|pts=36124|pts_time=0.752583|dts=36124|dts_time=0.752583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:b04fe85a packet|codec_type=audio|stream_index=0|pts=37084|pts_time=0.772583|dts=37084|dts_time=0.772583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:06797ece -packet|codec_type=audio|stream_index=0|pts=38044|pts_time=0.792583|dts=38044|dts_time=0.792583|duration=356|duration_time=0.007417|size=359|pos=841|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=38044|pts_time=0.792583|dts=38044|dts_time=0.792583|duration=356|duration_time=0.007417|size=359|pos=841|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 |data_hash=CRC32:01ca3f8f stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/48000|start_pts=0|start_time=0.000000|duration_ts=38756|duration=0.807417|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=41|extradata_size=19|extradata_hash=CRC32:58ba5ff3|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:ENCODER=opusenc from opus-tools 0.1.9|tag:ENCODER_OPTIONS=--discard-comments format|filename=intro-partial.opus|nb_streams=1|nb_programs=0|format_name=ogg|start_time=0.000000|duration=0.807417|size=10250|bit_rate=101558|probe_score=100 diff --git a/tests/ref/fate/ts-demux b/tests/ref/fate/ts-demux index 9702feb0d6..a90c65ce1c 100644 --- a/tests/ref/fate/ts-demux +++ b/tests/ref/fate/ts-demux @@ -1,48 +1,47 @@ -packet|codec_type=video|stream_index=0|pts=3912669846|pts_time=43474.109400|dts=3912665342|dts_time=43474.059356|duration=1501|duration_time=0.016678|size=114336|pos=376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912669846|pts_time=43474.109400|dts=3912665342|dts_time=43474.059356|duration=1501|duration_time=0.016678|size=114336|pos=376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:9bc8b561 -packet|codec_type=video|stream_index=0|pts=3912666843|pts_time=43474.076033|dts=3912666843|dts_time=43474.076033|duration=1501|duration_time=0.016678|size=12560|pos=122012|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912666843|pts_time=43474.076033|dts=3912666843|dts_time=43474.076033|duration=1501|duration_time=0.016678|size=12560|pos=122012|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:4f8c97dd -packet|codec_type=video|stream_index=0|pts=3912668345|pts_time=43474.092722|dts=3912668345|dts_time=43474.092722|duration=1501|duration_time=0.016678|size=12704|pos=135548|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912668345|pts_time=43474.092722|dts=3912668345|dts_time=43474.092722|duration=1501|duration_time=0.016678|size=12704|pos=135548|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:27f259db -packet|codec_type=video|stream_index=0|pts=3912674351|pts_time=43474.159456|dts=3912669846|dts_time=43474.109400|duration=1501|duration_time=0.016678|size=51976|pos=149084|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912674351|pts_time=43474.159456|dts=3912669846|dts_time=43474.109400|duration=1501|duration_time=0.016678|size=51976|pos=149084|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a6588b80 -packet|codec_type=video|stream_index=0|pts=3912671348|pts_time=43474.126089|dts=3912671348|dts_time=43474.126089|duration=1501|duration_time=0.016678|size=13096|pos=204356|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912671348|pts_time=43474.126089|dts=3912671348|dts_time=43474.126089|duration=1501|duration_time=0.016678|size=13096|pos=204356|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:33547f9f -packet|codec_type=video|stream_index=0|pts=3912672849|pts_time=43474.142767|dts=3912672849|dts_time=43474.142767|duration=1501|duration_time=0.016678|size=13744|pos=218456|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912672849|pts_time=43474.142767|dts=3912672849|dts_time=43474.142767|duration=1501|duration_time=0.016678|size=13744|pos=218456|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:547f3d4e -packet|codec_type=video|stream_index=0|pts=3912678855|pts_time=43474.209500|dts=3912674351|dts_time=43474.159456|duration=1501|duration_time=0.016678|size=56568|pos=232932|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912678855|pts_time=43474.209500|dts=3912674351|dts_time=43474.159456|duration=1501|duration_time=0.016678|size=56568|pos=232932|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:fb5f4b9e -packet|codec_type=video|stream_index=0|pts=3912675852|pts_time=43474.176133|dts=3912675852|dts_time=43474.176133|duration=1501|duration_time=0.016678|size=14720|pos=293092|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912675852|pts_time=43474.176133|dts=3912675852|dts_time=43474.176133|duration=1501|duration_time=0.016678|size=14720|pos=293092|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:1fb84db4 -packet|codec_type=video|stream_index=0|pts=3912677354|pts_time=43474.192822|dts=3912677354|dts_time=43474.192822|duration=1501|duration_time=0.016678|size=15216|pos=309072|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912677354|pts_time=43474.192822|dts=3912677354|dts_time=43474.192822|duration=1501|duration_time=0.016678|size=15216|pos=309072|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:77516f2c -packet|codec_type=video|stream_index=0|pts=3912683360|pts_time=43474.259556|dts=3912678855|dts_time=43474.209500|duration=1501|duration_time=0.016678|size=61720|pos=325240|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912683360|pts_time=43474.259556|dts=3912678855|dts_time=43474.209500|duration=1501|duration_time=0.016678|size=61720|pos=325240|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:7e6594e5 -packet|codec_type=video|stream_index=0|pts=3912680357|pts_time=43474.226189|dts=3912680357|dts_time=43474.226189|duration=1501|duration_time=0.016678|size=17416|pos=390852|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912680357|pts_time=43474.226189|dts=3912680357|dts_time=43474.226189|duration=1501|duration_time=0.016678|size=17416|pos=390852|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:31c8b89d -packet|codec_type=audio|stream_index=1|pts=3912633305|pts_time=43473.703389|dts=3912633305|dts_time=43473.703389|duration=2880|duration_time=0.032000|size=1536|pos=218080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=1|pts=3912633305|pts_time=43473.703389|dts=3912633305|dts_time=43473.703389|duration=2880|duration_time=0.032000|size=1536|pos=218080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:25b60d38 packet|codec_type=audio|stream_index=1|pts=3912636185|pts_time=43473.735389|dts=3912636185|dts_time=43473.735389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_|data_hash=CRC32:d4e30aaf packet|codec_type=audio|stream_index=1|pts=3912639065|pts_time=43473.767389|dts=3912639065|dts_time=43473.767389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_|data_hash=CRC32:32d6d14d -packet|codec_type=audio|stream_index=2|pts=3912634060|pts_time=43473.711778|dts=3912634060|dts_time=43473.711778|duration=2880|duration_time=0.032000|size=768|pos=235564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=2|pts=3912634060|pts_time=43473.711778|dts=3912634060|dts_time=43473.711778|duration=2880|duration_time=0.032000|size=768|pos=235564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:34b350c9 packet|codec_type=audio|stream_index=2|pts=3912636940|pts_time=43473.743778|dts=3912636940|dts_time=43473.743778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_|data_hash=CRC32:457881f8 packet|codec_type=audio|stream_index=2|pts=3912639820|pts_time=43473.775778|dts=3912639820|dts_time=43473.775778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_|data_hash=CRC32:1abb0d9a -packet|codec_type=video|stream_index=0|pts=3912681858|pts_time=43474.242867|dts=3912681858|dts_time=43474.242867|duration=1501|duration_time=0.016678|size=18144|pos=409464|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912681858|pts_time=43474.242867|dts=3912681858|dts_time=43474.242867|duration=1501|duration_time=0.016678|size=18144|pos=409464|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:826f8e8e -packet|codec_type=video|stream_index=0|pts=3912687864|pts_time=43474.309600|dts=3912683360|dts_time=43474.259556|duration=1501|duration_time=0.016678|size=56848|pos=428640|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912687864|pts_time=43474.309600|dts=3912683360|dts_time=43474.259556|duration=1501|duration_time=0.016678|size=56848|pos=428640|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6b15be8c -packet|codec_type=video|stream_index=0|pts=3912684861|pts_time=43474.276233|dts=3912684861|dts_time=43474.276233|duration=1501|duration_time=0.016678|size=16296|pos=489176|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912684861|pts_time=43474.276233|dts=3912684861|dts_time=43474.276233|duration=1501|duration_time=0.016678|size=16296|pos=489176|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:911b1649 -packet|codec_type=audio|stream_index=1|pts=3912641945|pts_time=43473.799389|dts=3912641945|dts_time=43473.799389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=1|pts=3912641945|pts_time=43473.799389|dts=3912641945|dts_time=43473.799389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d2f2012f -packet|codec_type=audio|stream_index=2|pts=3912642700|pts_time=43473.807778|dts=3912642700|dts_time=43473.807778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=2|pts=3912642700|pts_time=43473.807778|dts=3912642700|dts_time=43473.807778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3dad674a packet|codec_type=video|stream_index=0|pts=3912686363|pts_time=43474.292922|dts=3912686363|dts_time=43474.292922|duration=1501|duration_time=0.016678|size=4944|pos=506660|flags=__|data_hash=CRC32:54a86cbb packet|codec_type=audio|stream_index=1|pts=3912644825|pts_time=43473.831389|dts=3912644825|dts_time=43473.831389|duration=2880|duration_time=0.032000|size=906|pos=474888|flags=K_|data_hash=CRC32:0893d398 packet|codec_type=audio|stream_index=2|pts=3912645580|pts_time=43473.839778|dts=3912645580|dts_time=43473.839778|duration=2880|duration_time=0.032000|size=354|pos=491808|flags=K_|data_hash=CRC32:f5963fa6 -stream|index=0|codec_name=mpeg2video|profile=4|codec_type=video|codec_tag_string=[2][0][0][0]|codec_tag=0x0002|width=1280|height=720|coded_width=0|coded_height=0|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=4|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|id=0x31|r_frame_rate=60000/1001|avg_frame_rate=60000/1001|time_base=1/90000|start_pts=3912669846|start_time=43474.109400|duration_ts=19519|duration=0.216878|bit_rate=15000000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=15|extradata_size=150|extradata_hash=CRC32:53134fa8|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 -side_data|side_data_type=CPB properties|max_bitrate=15000000|min_bitrate=0|avg_bitrate=0|buffer_size=9781248|vbv_delay=-1 +stream|index=0|codec_name=mpeg2video|profile=4|codec_type=video|codec_tag_string=[2][0][0][0]|codec_tag=0x0002|width=1280|height=720|coded_width=0|coded_height=0|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=4|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|id=0x31|r_frame_rate=60000/1001|avg_frame_rate=60000/1001|time_base=1/90000|start_pts=3912669846|start_time=43474.109400|duration_ts=19519|duration=0.216878|bit_rate=15000000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=15|extradata_size=150|extradata_hash=CRC32:53134fa8|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|side_data|side_data_type=CPB properties|max_bitrate=15000000|min_bitrate=0|avg_bitrate=0|buffer_size=9781248|vbv_delay=-1 stream|index=1|codec_name=ac3|profile=unknown|codec_type=audio|codec_tag_string=[4][0][0][0]|codec_tag=0x0004|sample_fmt=fltp|sample_rate=48000|channels=6|channel_layout=5.1(side)|bits_per_sample=0|id=0x34|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=3912633305|start_time=43473.703389|duration_ts=14400|duration=0.160000|bit_rate=384000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=5|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:language=eng stream|index=2|codec_name=ac3|profile=unknown|codec_type=audio|codec_tag_string=[4][0][0][0]|codec_tag=0x0004|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=0x35|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=3912634060|start_time=43473.711778|duration_ts=14400|duration=0.160000|bit_rate=192000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=5|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:language=es format|filename=mp3ac325-4864-small.ts|nb_streams=3|nb_programs=1|format_name=mpegts|start_time=43473.703389|duration=0.622889|size=512000|bit_rate=6575810|probe_score=50 diff --git a/tests/ref/fate/ts-opus-demux b/tests/ref/fate/ts-opus-demux index 6513c0d4c2..ba6059a019 100644 --- a/tests/ref/fate/ts-opus-demux +++ b/tests/ref/fate/ts-opus-demux @@ -1,1026 +1,1026 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1800|duration_time=0.020000|size=744|pos=376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1800|duration_time=0.020000|size=744|pos=376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:eec8d060 -packet|codec_type=audio|stream_index=0|pts=1800|pts_time=0.020000|dts=1800|dts_time=0.020000|duration=1800|duration_time=0.020000|size=743|pos=1316|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=1800|pts_time=0.020000|dts=1800|dts_time=0.020000|duration=1800|duration_time=0.020000|size=743|pos=1316|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c5307335 -packet|codec_type=audio|stream_index=0|pts=3600|pts_time=0.040000|dts=3600|dts_time=0.040000|duration=1800|duration_time=0.020000|size=747|pos=2256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=3600|pts_time=0.040000|dts=3600|dts_time=0.040000|duration=1800|duration_time=0.020000|size=747|pos=2256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6f1c0bfa -packet|codec_type=audio|stream_index=0|pts=5400|pts_time=0.060000|dts=5400|dts_time=0.060000|duration=1800|duration_time=0.020000|size=742|pos=3196|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=5400|pts_time=0.060000|dts=5400|dts_time=0.060000|duration=1800|duration_time=0.020000|size=742|pos=3196|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:765b2eab -packet|codec_type=audio|stream_index=0|pts=7200|pts_time=0.080000|dts=7200|dts_time=0.080000|duration=1800|duration_time=0.020000|size=752|pos=4136|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=7200|pts_time=0.080000|dts=7200|dts_time=0.080000|duration=1800|duration_time=0.020000|size=752|pos=4136|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:490463dd -packet|codec_type=audio|stream_index=0|pts=9000|pts_time=0.100000|dts=9000|dts_time=0.100000|duration=1800|duration_time=0.020000|size=753|pos=5076|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=9000|pts_time=0.100000|dts=9000|dts_time=0.100000|duration=1800|duration_time=0.020000|size=753|pos=5076|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:beef1221 -packet|codec_type=audio|stream_index=0|pts=10800|pts_time=0.120000|dts=10800|dts_time=0.120000|duration=1800|duration_time=0.020000|size=756|pos=6016|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=10800|pts_time=0.120000|dts=10800|dts_time=0.120000|duration=1800|duration_time=0.020000|size=756|pos=6016|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7814e1fe -packet|codec_type=audio|stream_index=0|pts=12600|pts_time=0.140000|dts=12600|dts_time=0.140000|duration=1800|duration_time=0.020000|size=761|pos=6956|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=12600|pts_time=0.140000|dts=12600|dts_time=0.140000|duration=1800|duration_time=0.020000|size=761|pos=6956|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1e28bf7d -packet|codec_type=audio|stream_index=0|pts=14400|pts_time=0.160000|dts=14400|dts_time=0.160000|duration=1800|duration_time=0.020000|size=755|pos=7896|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=14400|pts_time=0.160000|dts=14400|dts_time=0.160000|duration=1800|duration_time=0.020000|size=755|pos=7896|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ac39390f -packet|codec_type=audio|stream_index=0|pts=16200|pts_time=0.180000|dts=16200|dts_time=0.180000|duration=1800|duration_time=0.020000|size=760|pos=8836|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=16200|pts_time=0.180000|dts=16200|dts_time=0.180000|duration=1800|duration_time=0.020000|size=760|pos=8836|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:56129f6c -packet|codec_type=audio|stream_index=0|pts=18000|pts_time=0.200000|dts=18000|dts_time=0.200000|duration=1800|duration_time=0.020000|size=759|pos=10152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=18000|pts_time=0.200000|dts=18000|dts_time=0.200000|duration=1800|duration_time=0.020000|size=759|pos=10152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:444cf0b3 -packet|codec_type=audio|stream_index=0|pts=19800|pts_time=0.220000|dts=19800|dts_time=0.220000|duration=1800|duration_time=0.020000|size=760|pos=11092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=19800|pts_time=0.220000|dts=19800|dts_time=0.220000|duration=1800|duration_time=0.020000|size=760|pos=11092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b26188cc -packet|codec_type=audio|stream_index=0|pts=21600|pts_time=0.240000|dts=21600|dts_time=0.240000|duration=1800|duration_time=0.020000|size=762|pos=12032|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=21600|pts_time=0.240000|dts=21600|dts_time=0.240000|duration=1800|duration_time=0.020000|size=762|pos=12032|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:550b5ea5 -packet|codec_type=audio|stream_index=0|pts=23400|pts_time=0.260000|dts=23400|dts_time=0.260000|duration=1800|duration_time=0.020000|size=761|pos=12972|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=23400|pts_time=0.260000|dts=23400|dts_time=0.260000|duration=1800|duration_time=0.020000|size=761|pos=12972|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3b587071 -packet|codec_type=audio|stream_index=0|pts=25200|pts_time=0.280000|dts=25200|dts_time=0.280000|duration=1800|duration_time=0.020000|size=758|pos=13912|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=25200|pts_time=0.280000|dts=25200|dts_time=0.280000|duration=1800|duration_time=0.020000|size=758|pos=13912|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c655d80f -packet|codec_type=audio|stream_index=0|pts=27000|pts_time=0.300000|dts=27000|dts_time=0.300000|duration=1800|duration_time=0.020000|size=756|pos=14852|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=27000|pts_time=0.300000|dts=27000|dts_time=0.300000|duration=1800|duration_time=0.020000|size=756|pos=14852|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4734bf58 -packet|codec_type=audio|stream_index=0|pts=28800|pts_time=0.320000|dts=28800|dts_time=0.320000|duration=1800|duration_time=0.020000|size=762|pos=15792|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=28800|pts_time=0.320000|dts=28800|dts_time=0.320000|duration=1800|duration_time=0.020000|size=762|pos=15792|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:58ddcd0e -packet|codec_type=audio|stream_index=0|pts=30600|pts_time=0.340000|dts=30600|dts_time=0.340000|duration=1800|duration_time=0.020000|size=763|pos=16732|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=30600|pts_time=0.340000|dts=30600|dts_time=0.340000|duration=1800|duration_time=0.020000|size=763|pos=16732|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:50786001 -packet|codec_type=audio|stream_index=0|pts=32400|pts_time=0.360000|dts=32400|dts_time=0.360000|duration=1800|duration_time=0.020000|size=765|pos=17672|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=32400|pts_time=0.360000|dts=32400|dts_time=0.360000|duration=1800|duration_time=0.020000|size=765|pos=17672|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4c8c5dc8 -packet|codec_type=audio|stream_index=0|pts=34200|pts_time=0.380000|dts=34200|dts_time=0.380000|duration=1800|duration_time=0.020000|size=772|pos=18612|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=34200|pts_time=0.380000|dts=34200|dts_time=0.380000|duration=1800|duration_time=0.020000|size=772|pos=18612|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ad3f1eda -packet|codec_type=audio|stream_index=0|pts=36000|pts_time=0.400000|dts=36000|dts_time=0.400000|duration=1800|duration_time=0.020000|size=817|pos=19928|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=36000|pts_time=0.400000|dts=36000|dts_time=0.400000|duration=1800|duration_time=0.020000|size=817|pos=19928|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8b7c8437 -packet|codec_type=audio|stream_index=0|pts=37800|pts_time=0.420000|dts=37800|dts_time=0.420000|duration=1800|duration_time=0.020000|size=828|pos=20868|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=37800|pts_time=0.420000|dts=37800|dts_time=0.420000|duration=1800|duration_time=0.020000|size=828|pos=20868|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c52621e3 -packet|codec_type=audio|stream_index=0|pts=39600|pts_time=0.440000|dts=39600|dts_time=0.440000|duration=1800|duration_time=0.020000|size=952|pos=21808|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=39600|pts_time=0.440000|dts=39600|dts_time=0.440000|duration=1800|duration_time=0.020000|size=952|pos=21808|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4b34b632 -packet|codec_type=audio|stream_index=0|pts=41400|pts_time=0.460000|dts=41400|dts_time=0.460000|duration=1800|duration_time=0.020000|size=819|pos=22936|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=41400|pts_time=0.460000|dts=41400|dts_time=0.460000|duration=1800|duration_time=0.020000|size=819|pos=22936|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:79f06d2c -packet|codec_type=audio|stream_index=0|pts=43200|pts_time=0.480000|dts=43200|dts_time=0.480000|duration=1800|duration_time=0.020000|size=816|pos=23876|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=43200|pts_time=0.480000|dts=43200|dts_time=0.480000|duration=1800|duration_time=0.020000|size=816|pos=23876|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:31136ff8 -packet|codec_type=audio|stream_index=0|pts=45000|pts_time=0.500000|dts=45000|dts_time=0.500000|duration=1800|duration_time=0.020000|size=825|pos=24816|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=45000|pts_time=0.500000|dts=45000|dts_time=0.500000|duration=1800|duration_time=0.020000|size=825|pos=24816|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d6cd17f2 -packet|codec_type=audio|stream_index=0|pts=46800|pts_time=0.520000|dts=46800|dts_time=0.520000|duration=1800|duration_time=0.020000|size=814|pos=25756|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=46800|pts_time=0.520000|dts=46800|dts_time=0.520000|duration=1800|duration_time=0.020000|size=814|pos=25756|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bd4ada7b -packet|codec_type=audio|stream_index=0|pts=48600|pts_time=0.540000|dts=48600|dts_time=0.540000|duration=1800|duration_time=0.020000|size=824|pos=26696|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=48600|pts_time=0.540000|dts=48600|dts_time=0.540000|duration=1800|duration_time=0.020000|size=824|pos=26696|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59132b5d -packet|codec_type=audio|stream_index=0|pts=50400|pts_time=0.560000|dts=50400|dts_time=0.560000|duration=1800|duration_time=0.020000|size=815|pos=27636|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=50400|pts_time=0.560000|dts=50400|dts_time=0.560000|duration=1800|duration_time=0.020000|size=815|pos=27636|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6d3ba392 -packet|codec_type=audio|stream_index=0|pts=52200|pts_time=0.580000|dts=52200|dts_time=0.580000|duration=1800|duration_time=0.020000|size=824|pos=28576|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=52200|pts_time=0.580000|dts=52200|dts_time=0.580000|duration=1800|duration_time=0.020000|size=824|pos=28576|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b9341220 -packet|codec_type=audio|stream_index=0|pts=54000|pts_time=0.600000|dts=54000|dts_time=0.600000|duration=1800|duration_time=0.020000|size=822|pos=29892|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=54000|pts_time=0.600000|dts=54000|dts_time=0.600000|duration=1800|duration_time=0.020000|size=822|pos=29892|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cd0b0be2 -packet|codec_type=audio|stream_index=0|pts=55800|pts_time=0.620000|dts=55800|dts_time=0.620000|duration=1800|duration_time=0.020000|size=819|pos=30832|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=55800|pts_time=0.620000|dts=55800|dts_time=0.620000|duration=1800|duration_time=0.020000|size=819|pos=30832|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c0a97918 -packet|codec_type=audio|stream_index=0|pts=57600|pts_time=0.640000|dts=57600|dts_time=0.640000|duration=1800|duration_time=0.020000|size=817|pos=31772|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=57600|pts_time=0.640000|dts=57600|dts_time=0.640000|duration=1800|duration_time=0.020000|size=817|pos=31772|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b4da2c7e -packet|codec_type=audio|stream_index=0|pts=59400|pts_time=0.660000|dts=59400|dts_time=0.660000|duration=1800|duration_time=0.020000|size=826|pos=32712|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=59400|pts_time=0.660000|dts=59400|dts_time=0.660000|duration=1800|duration_time=0.020000|size=826|pos=32712|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aaf0a9b2 -packet|codec_type=audio|stream_index=0|pts=61200|pts_time=0.680000|dts=61200|dts_time=0.680000|duration=1800|duration_time=0.020000|size=822|pos=33652|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=61200|pts_time=0.680000|dts=61200|dts_time=0.680000|duration=1800|duration_time=0.020000|size=822|pos=33652|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a09994ed -packet|codec_type=audio|stream_index=0|pts=63000|pts_time=0.700000|dts=63000|dts_time=0.700000|duration=1800|duration_time=0.020000|size=815|pos=34592|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=63000|pts_time=0.700000|dts=63000|dts_time=0.700000|duration=1800|duration_time=0.020000|size=815|pos=34592|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ded67e51 -packet|codec_type=audio|stream_index=0|pts=64800|pts_time=0.720000|dts=64800|dts_time=0.720000|duration=1800|duration_time=0.020000|size=820|pos=35532|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=64800|pts_time=0.720000|dts=64800|dts_time=0.720000|duration=1800|duration_time=0.020000|size=820|pos=35532|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:17f0a2c0 -packet|codec_type=audio|stream_index=0|pts=66600|pts_time=0.740000|dts=66600|dts_time=0.740000|duration=1800|duration_time=0.020000|size=828|pos=36472|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=66600|pts_time=0.740000|dts=66600|dts_time=0.740000|duration=1800|duration_time=0.020000|size=828|pos=36472|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:92d1d4ad -packet|codec_type=audio|stream_index=0|pts=68400|pts_time=0.760000|dts=68400|dts_time=0.760000|duration=1800|duration_time=0.020000|size=828|pos=37412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=68400|pts_time=0.760000|dts=68400|dts_time=0.760000|duration=1800|duration_time=0.020000|size=828|pos=37412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3752c787 -packet|codec_type=audio|stream_index=0|pts=70200|pts_time=0.780000|dts=70200|dts_time=0.780000|duration=1800|duration_time=0.020000|size=942|pos=38352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=70200|pts_time=0.780000|dts=70200|dts_time=0.780000|duration=1800|duration_time=0.020000|size=942|pos=38352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ab24f03b -packet|codec_type=audio|stream_index=0|pts=72000|pts_time=0.800000|dts=72000|dts_time=0.800000|duration=1800|duration_time=0.020000|size=809|pos=39856|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=72000|pts_time=0.800000|dts=72000|dts_time=0.800000|duration=1800|duration_time=0.020000|size=809|pos=39856|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:920e19f5 -packet|codec_type=audio|stream_index=0|pts=73800|pts_time=0.820000|dts=73800|dts_time=0.820000|duration=1800|duration_time=0.020000|size=823|pos=40796|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=73800|pts_time=0.820000|dts=73800|dts_time=0.820000|duration=1800|duration_time=0.020000|size=823|pos=40796|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:951b6d50 -packet|codec_type=audio|stream_index=0|pts=75600|pts_time=0.840000|dts=75600|dts_time=0.840000|duration=1800|duration_time=0.020000|size=827|pos=41736|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=75600|pts_time=0.840000|dts=75600|dts_time=0.840000|duration=1800|duration_time=0.020000|size=827|pos=41736|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cfc9eb30 -packet|codec_type=audio|stream_index=0|pts=77400|pts_time=0.860000|dts=77400|dts_time=0.860000|duration=1800|duration_time=0.020000|size=823|pos=42676|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=77400|pts_time=0.860000|dts=77400|dts_time=0.860000|duration=1800|duration_time=0.020000|size=823|pos=42676|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dd66bb72 -packet|codec_type=audio|stream_index=0|pts=79200|pts_time=0.880000|dts=79200|dts_time=0.880000|duration=1800|duration_time=0.020000|size=825|pos=43616|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=79200|pts_time=0.880000|dts=79200|dts_time=0.880000|duration=1800|duration_time=0.020000|size=825|pos=43616|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:67b1c809 -packet|codec_type=audio|stream_index=0|pts=81000|pts_time=0.900000|dts=81000|dts_time=0.900000|duration=1800|duration_time=0.020000|size=828|pos=44556|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=81000|pts_time=0.900000|dts=81000|dts_time=0.900000|duration=1800|duration_time=0.020000|size=828|pos=44556|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:94d441b0 -packet|codec_type=audio|stream_index=0|pts=82800|pts_time=0.920000|dts=82800|dts_time=0.920000|duration=1800|duration_time=0.020000|size=823|pos=45496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=82800|pts_time=0.920000|dts=82800|dts_time=0.920000|duration=1800|duration_time=0.020000|size=823|pos=45496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:178471e0 -packet|codec_type=audio|stream_index=0|pts=84600|pts_time=0.940000|dts=84600|dts_time=0.940000|duration=1800|duration_time=0.020000|size=817|pos=46436|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=84600|pts_time=0.940000|dts=84600|dts_time=0.940000|duration=1800|duration_time=0.020000|size=817|pos=46436|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:90e30fb2 -packet|codec_type=audio|stream_index=0|pts=86400|pts_time=0.960000|dts=86400|dts_time=0.960000|duration=1800|duration_time=0.020000|size=813|pos=47376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=86400|pts_time=0.960000|dts=86400|dts_time=0.960000|duration=1800|duration_time=0.020000|size=813|pos=47376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dd4e1d03 -packet|codec_type=audio|stream_index=0|pts=88200|pts_time=0.980000|dts=88200|dts_time=0.980000|duration=1800|duration_time=0.020000|size=809|pos=48316|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=88200|pts_time=0.980000|dts=88200|dts_time=0.980000|duration=1800|duration_time=0.020000|size=809|pos=48316|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0e059caf -packet|codec_type=audio|stream_index=0|pts=90000|pts_time=1.000000|dts=90000|dts_time=1.000000|duration=1800|duration_time=0.020000|size=813|pos=49632|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=90000|pts_time=1.000000|dts=90000|dts_time=1.000000|duration=1800|duration_time=0.020000|size=813|pos=49632|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1981fa52 -packet|codec_type=audio|stream_index=0|pts=91800|pts_time=1.020000|dts=91800|dts_time=1.020000|duration=1800|duration_time=0.020000|size=820|pos=50572|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=91800|pts_time=1.020000|dts=91800|dts_time=1.020000|duration=1800|duration_time=0.020000|size=820|pos=50572|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6af0ac25 -packet|codec_type=audio|stream_index=0|pts=93600|pts_time=1.040000|dts=93600|dts_time=1.040000|duration=1800|duration_time=0.020000|size=818|pos=51512|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=93600|pts_time=1.040000|dts=93600|dts_time=1.040000|duration=1800|duration_time=0.020000|size=818|pos=51512|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4ed14497 -packet|codec_type=audio|stream_index=0|pts=95400|pts_time=1.060000|dts=95400|dts_time=1.060000|duration=1800|duration_time=0.020000|size=825|pos=52452|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=95400|pts_time=1.060000|dts=95400|dts_time=1.060000|duration=1800|duration_time=0.020000|size=825|pos=52452|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b1712b61 -packet|codec_type=audio|stream_index=0|pts=97200|pts_time=1.080000|dts=97200|dts_time=1.080000|duration=1800|duration_time=0.020000|size=808|pos=53392|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=97200|pts_time=1.080000|dts=97200|dts_time=1.080000|duration=1800|duration_time=0.020000|size=808|pos=53392|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:97469bbe -packet|codec_type=audio|stream_index=0|pts=99000|pts_time=1.100000|dts=99000|dts_time=1.100000|duration=1800|duration_time=0.020000|size=774|pos=54332|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=99000|pts_time=1.100000|dts=99000|dts_time=1.100000|duration=1800|duration_time=0.020000|size=774|pos=54332|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f2f922fc -packet|codec_type=audio|stream_index=0|pts=100800|pts_time=1.120000|dts=100800|dts_time=1.120000|duration=1800|duration_time=0.020000|size=774|pos=55272|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=100800|pts_time=1.120000|dts=100800|dts_time=1.120000|duration=1800|duration_time=0.020000|size=774|pos=55272|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:024f521d -packet|codec_type=audio|stream_index=0|pts=102600|pts_time=1.140000|dts=102600|dts_time=1.140000|duration=1800|duration_time=0.020000|size=777|pos=56212|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=102600|pts_time=1.140000|dts=102600|dts_time=1.140000|duration=1800|duration_time=0.020000|size=777|pos=56212|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:674d82ba -packet|codec_type=audio|stream_index=0|pts=104400|pts_time=1.160000|dts=104400|dts_time=1.160000|duration=1800|duration_time=0.020000|size=776|pos=57152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=104400|pts_time=1.160000|dts=104400|dts_time=1.160000|duration=1800|duration_time=0.020000|size=776|pos=57152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:79409537 -packet|codec_type=audio|stream_index=0|pts=106200|pts_time=1.180000|dts=106200|dts_time=1.180000|duration=1800|duration_time=0.020000|size=779|pos=58092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=106200|pts_time=1.180000|dts=106200|dts_time=1.180000|duration=1800|duration_time=0.020000|size=779|pos=58092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aad393ee -packet|codec_type=audio|stream_index=0|pts=108000|pts_time=1.200000|dts=108000|dts_time=1.200000|duration=1800|duration_time=0.020000|size=779|pos=59408|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=108000|pts_time=1.200000|dts=108000|dts_time=1.200000|duration=1800|duration_time=0.020000|size=779|pos=59408|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9e2dee75 -packet|codec_type=audio|stream_index=0|pts=109800|pts_time=1.220000|dts=109800|dts_time=1.220000|duration=1800|duration_time=0.020000|size=774|pos=60348|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=109800|pts_time=1.220000|dts=109800|dts_time=1.220000|duration=1800|duration_time=0.020000|size=774|pos=60348|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1d8953b4 -packet|codec_type=audio|stream_index=0|pts=111600|pts_time=1.240000|dts=111600|dts_time=1.240000|duration=1800|duration_time=0.020000|size=772|pos=61288|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=111600|pts_time=1.240000|dts=111600|dts_time=1.240000|duration=1800|duration_time=0.020000|size=772|pos=61288|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3f191e37 -packet|codec_type=audio|stream_index=0|pts=113400|pts_time=1.260000|dts=113400|dts_time=1.260000|duration=1800|duration_time=0.020000|size=779|pos=62228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=113400|pts_time=1.260000|dts=113400|dts_time=1.260000|duration=1800|duration_time=0.020000|size=779|pos=62228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8e05df12 -packet|codec_type=audio|stream_index=0|pts=115200|pts_time=1.280000|dts=115200|dts_time=1.280000|duration=1800|duration_time=0.020000|size=774|pos=63168|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=115200|pts_time=1.280000|dts=115200|dts_time=1.280000|duration=1800|duration_time=0.020000|size=774|pos=63168|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d3d2e07c -packet|codec_type=audio|stream_index=0|pts=117000|pts_time=1.300000|dts=117000|dts_time=1.300000|duration=1800|duration_time=0.020000|size=772|pos=64108|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=117000|pts_time=1.300000|dts=117000|dts_time=1.300000|duration=1800|duration_time=0.020000|size=772|pos=64108|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:22e0dee4 -packet|codec_type=audio|stream_index=0|pts=118800|pts_time=1.320000|dts=118800|dts_time=1.320000|duration=1800|duration_time=0.020000|size=771|pos=65048|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=118800|pts_time=1.320000|dts=118800|dts_time=1.320000|duration=1800|duration_time=0.020000|size=771|pos=65048|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7e1fae18 -packet|codec_type=audio|stream_index=0|pts=120600|pts_time=1.340000|dts=120600|dts_time=1.340000|duration=1800|duration_time=0.020000|size=776|pos=65988|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=120600|pts_time=1.340000|dts=120600|dts_time=1.340000|duration=1800|duration_time=0.020000|size=776|pos=65988|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:213724a0 -packet|codec_type=audio|stream_index=0|pts=122400|pts_time=1.360000|dts=122400|dts_time=1.360000|duration=1800|duration_time=0.020000|size=776|pos=66928|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=122400|pts_time=1.360000|dts=122400|dts_time=1.360000|duration=1800|duration_time=0.020000|size=776|pos=66928|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f6018f97 -packet|codec_type=audio|stream_index=0|pts=124200|pts_time=1.380000|dts=124200|dts_time=1.380000|duration=1800|duration_time=0.020000|size=777|pos=67868|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=124200|pts_time=1.380000|dts=124200|dts_time=1.380000|duration=1800|duration_time=0.020000|size=777|pos=67868|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d917e577 -packet|codec_type=audio|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=1800|duration_time=0.020000|size=779|pos=69184|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=1800|duration_time=0.020000|size=779|pos=69184|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2860d19c -packet|codec_type=audio|stream_index=0|pts=127800|pts_time=1.420000|dts=127800|dts_time=1.420000|duration=1800|duration_time=0.020000|size=779|pos=70124|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=127800|pts_time=1.420000|dts=127800|dts_time=1.420000|duration=1800|duration_time=0.020000|size=779|pos=70124|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:799e404b -packet|codec_type=audio|stream_index=0|pts=129600|pts_time=1.440000|dts=129600|dts_time=1.440000|duration=1800|duration_time=0.020000|size=774|pos=71064|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=129600|pts_time=1.440000|dts=129600|dts_time=1.440000|duration=1800|duration_time=0.020000|size=774|pos=71064|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a4c43eaa -packet|codec_type=audio|stream_index=0|pts=131400|pts_time=1.460000|dts=131400|dts_time=1.460000|duration=1800|duration_time=0.020000|size=779|pos=72004|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=131400|pts_time=1.460000|dts=131400|dts_time=1.460000|duration=1800|duration_time=0.020000|size=779|pos=72004|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4aa2d0c3 -packet|codec_type=audio|stream_index=0|pts=133200|pts_time=1.480000|dts=133200|dts_time=1.480000|duration=1800|duration_time=0.020000|size=782|pos=72944|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=133200|pts_time=1.480000|dts=133200|dts_time=1.480000|duration=1800|duration_time=0.020000|size=782|pos=72944|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b5e19460 -packet|codec_type=audio|stream_index=0|pts=135000|pts_time=1.500000|dts=135000|dts_time=1.500000|duration=1800|duration_time=0.020000|size=776|pos=73884|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=135000|pts_time=1.500000|dts=135000|dts_time=1.500000|duration=1800|duration_time=0.020000|size=776|pos=73884|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:32445f6b -packet|codec_type=audio|stream_index=0|pts=136800|pts_time=1.520000|dts=136800|dts_time=1.520000|duration=1800|duration_time=0.020000|size=778|pos=74824|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=136800|pts_time=1.520000|dts=136800|dts_time=1.520000|duration=1800|duration_time=0.020000|size=778|pos=74824|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6f370fec -packet|codec_type=audio|stream_index=0|pts=138600|pts_time=1.540000|dts=138600|dts_time=1.540000|duration=1800|duration_time=0.020000|size=777|pos=75764|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=138600|pts_time=1.540000|dts=138600|dts_time=1.540000|duration=1800|duration_time=0.020000|size=777|pos=75764|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:43e04e6d -packet|codec_type=audio|stream_index=0|pts=140400|pts_time=1.560000|dts=140400|dts_time=1.560000|duration=1800|duration_time=0.020000|size=785|pos=76704|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=140400|pts_time=1.560000|dts=140400|dts_time=1.560000|duration=1800|duration_time=0.020000|size=785|pos=76704|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5ed32f7e -packet|codec_type=audio|stream_index=0|pts=142200|pts_time=1.580000|dts=142200|dts_time=1.580000|duration=1800|duration_time=0.020000|size=782|pos=77644|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=142200|pts_time=1.580000|dts=142200|dts_time=1.580000|duration=1800|duration_time=0.020000|size=782|pos=77644|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ead85ef4 -packet|codec_type=audio|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=1800|duration_time=0.020000|size=782|pos=78960|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=1800|duration_time=0.020000|size=782|pos=78960|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5f283747 -packet|codec_type=audio|stream_index=0|pts=145800|pts_time=1.620000|dts=145800|dts_time=1.620000|duration=1800|duration_time=0.020000|size=780|pos=79900|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=145800|pts_time=1.620000|dts=145800|dts_time=1.620000|duration=1800|duration_time=0.020000|size=780|pos=79900|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f4aa30a5 -packet|codec_type=audio|stream_index=0|pts=147600|pts_time=1.640000|dts=147600|dts_time=1.640000|duration=1800|duration_time=0.020000|size=776|pos=80840|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=147600|pts_time=1.640000|dts=147600|dts_time=1.640000|duration=1800|duration_time=0.020000|size=776|pos=80840|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ad09e32c -packet|codec_type=audio|stream_index=0|pts=149400|pts_time=1.660000|dts=149400|dts_time=1.660000|duration=1800|duration_time=0.020000|size=780|pos=81780|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=149400|pts_time=1.660000|dts=149400|dts_time=1.660000|duration=1800|duration_time=0.020000|size=780|pos=81780|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57f8004d -packet|codec_type=audio|stream_index=0|pts=151200|pts_time=1.680000|dts=151200|dts_time=1.680000|duration=1800|duration_time=0.020000|size=784|pos=82720|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=151200|pts_time=1.680000|dts=151200|dts_time=1.680000|duration=1800|duration_time=0.020000|size=784|pos=82720|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d862a139 -packet|codec_type=audio|stream_index=0|pts=153000|pts_time=1.700000|dts=153000|dts_time=1.700000|duration=1800|duration_time=0.020000|size=776|pos=83660|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=153000|pts_time=1.700000|dts=153000|dts_time=1.700000|duration=1800|duration_time=0.020000|size=776|pos=83660|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:29ebd249 -packet|codec_type=audio|stream_index=0|pts=154800|pts_time=1.720000|dts=154800|dts_time=1.720000|duration=1800|duration_time=0.020000|size=777|pos=84600|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=154800|pts_time=1.720000|dts=154800|dts_time=1.720000|duration=1800|duration_time=0.020000|size=777|pos=84600|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5af83f3e -packet|codec_type=audio|stream_index=0|pts=156600|pts_time=1.740000|dts=156600|dts_time=1.740000|duration=1800|duration_time=0.020000|size=783|pos=85540|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=156600|pts_time=1.740000|dts=156600|dts_time=1.740000|duration=1800|duration_time=0.020000|size=783|pos=85540|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:78784213 -packet|codec_type=audio|stream_index=0|pts=158400|pts_time=1.760000|dts=158400|dts_time=1.760000|duration=1800|duration_time=0.020000|size=780|pos=86480|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=158400|pts_time=1.760000|dts=158400|dts_time=1.760000|duration=1800|duration_time=0.020000|size=780|pos=86480|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cccb4c08 -packet|codec_type=audio|stream_index=0|pts=160200|pts_time=1.780000|dts=160200|dts_time=1.780000|duration=1800|duration_time=0.020000|size=782|pos=87420|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=160200|pts_time=1.780000|dts=160200|dts_time=1.780000|duration=1800|duration_time=0.020000|size=782|pos=87420|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:36520804 -packet|codec_type=audio|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=1800|duration_time=0.020000|size=848|pos=88736|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=1800|duration_time=0.020000|size=848|pos=88736|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9235baa -packet|codec_type=audio|stream_index=0|pts=163800|pts_time=1.820000|dts=163800|dts_time=1.820000|duration=1800|duration_time=0.020000|size=849|pos=89676|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=163800|pts_time=1.820000|dts=163800|dts_time=1.820000|duration=1800|duration_time=0.020000|size=849|pos=89676|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57ae2eef -packet|codec_type=audio|stream_index=0|pts=165600|pts_time=1.840000|dts=165600|dts_time=1.840000|duration=1800|duration_time=0.020000|size=783|pos=90616|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=165600|pts_time=1.840000|dts=165600|dts_time=1.840000|duration=1800|duration_time=0.020000|size=783|pos=90616|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:474f3232 -packet|codec_type=audio|stream_index=0|pts=167400|pts_time=1.860000|dts=167400|dts_time=1.860000|duration=1800|duration_time=0.020000|size=784|pos=91556|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=167400|pts_time=1.860000|dts=167400|dts_time=1.860000|duration=1800|duration_time=0.020000|size=784|pos=91556|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9a51d488 -packet|codec_type=audio|stream_index=0|pts=169200|pts_time=1.880000|dts=169200|dts_time=1.880000|duration=1800|duration_time=0.020000|size=785|pos=92496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=169200|pts_time=1.880000|dts=169200|dts_time=1.880000|duration=1800|duration_time=0.020000|size=785|pos=92496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:919bc794 -packet|codec_type=audio|stream_index=0|pts=171000|pts_time=1.900000|dts=171000|dts_time=1.900000|duration=1800|duration_time=0.020000|size=783|pos=93436|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=171000|pts_time=1.900000|dts=171000|dts_time=1.900000|duration=1800|duration_time=0.020000|size=783|pos=93436|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ed8214ad -packet|codec_type=audio|stream_index=0|pts=172800|pts_time=1.920000|dts=172800|dts_time=1.920000|duration=1800|duration_time=0.020000|size=876|pos=94376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=172800|pts_time=1.920000|dts=172800|dts_time=1.920000|duration=1800|duration_time=0.020000|size=876|pos=94376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:72fcce4c -packet|codec_type=audio|stream_index=0|pts=174600|pts_time=1.940000|dts=174600|dts_time=1.940000|duration=1800|duration_time=0.020000|size=776|pos=95316|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=174600|pts_time=1.940000|dts=174600|dts_time=1.940000|duration=1800|duration_time=0.020000|size=776|pos=95316|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2a0143f4 -packet|codec_type=audio|stream_index=0|pts=176400|pts_time=1.960000|dts=176400|dts_time=1.960000|duration=1800|duration_time=0.020000|size=787|pos=96256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=176400|pts_time=1.960000|dts=176400|dts_time=1.960000|duration=1800|duration_time=0.020000|size=787|pos=96256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:94f1aae1 -packet|codec_type=audio|stream_index=0|pts=178200|pts_time=1.980000|dts=178200|dts_time=1.980000|duration=1800|duration_time=0.020000|size=781|pos=97196|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=178200|pts_time=1.980000|dts=178200|dts_time=1.980000|duration=1800|duration_time=0.020000|size=781|pos=97196|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5565737b -packet|codec_type=audio|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=1800|duration_time=0.020000|size=852|pos=98512|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=1800|duration_time=0.020000|size=852|pos=98512|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:daea61be -packet|codec_type=audio|stream_index=0|pts=181800|pts_time=2.020000|dts=181800|dts_time=2.020000|duration=1800|duration_time=0.020000|size=849|pos=99452|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=181800|pts_time=2.020000|dts=181800|dts_time=2.020000|duration=1800|duration_time=0.020000|size=849|pos=99452|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee704432 -packet|codec_type=audio|stream_index=0|pts=183600|pts_time=2.040000|dts=183600|dts_time=2.040000|duration=1800|duration_time=0.020000|size=873|pos=100392|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=183600|pts_time=2.040000|dts=183600|dts_time=2.040000|duration=1800|duration_time=0.020000|size=873|pos=100392|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:472aa214 -packet|codec_type=audio|stream_index=0|pts=185400|pts_time=2.060000|dts=185400|dts_time=2.060000|duration=1800|duration_time=0.020000|size=843|pos=101332|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=185400|pts_time=2.060000|dts=185400|dts_time=2.060000|duration=1800|duration_time=0.020000|size=843|pos=101332|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0b046703 -packet|codec_type=audio|stream_index=0|pts=187200|pts_time=2.080000|dts=187200|dts_time=2.080000|duration=1800|duration_time=0.020000|size=841|pos=102272|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=187200|pts_time=2.080000|dts=187200|dts_time=2.080000|duration=1800|duration_time=0.020000|size=841|pos=102272|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59bf9bd5 -packet|codec_type=audio|stream_index=0|pts=189000|pts_time=2.100000|dts=189000|dts_time=2.100000|duration=1800|duration_time=0.020000|size=777|pos=103212|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=189000|pts_time=2.100000|dts=189000|dts_time=2.100000|duration=1800|duration_time=0.020000|size=777|pos=103212|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:808ee658 -packet|codec_type=audio|stream_index=0|pts=190800|pts_time=2.120000|dts=190800|dts_time=2.120000|duration=1800|duration_time=0.020000|size=846|pos=104152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=190800|pts_time=2.120000|dts=190800|dts_time=2.120000|duration=1800|duration_time=0.020000|size=846|pos=104152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:db581c04 -packet|codec_type=audio|stream_index=0|pts=192600|pts_time=2.140000|dts=192600|dts_time=2.140000|duration=1800|duration_time=0.020000|size=782|pos=105092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=192600|pts_time=2.140000|dts=192600|dts_time=2.140000|duration=1800|duration_time=0.020000|size=782|pos=105092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:768d8d82 -packet|codec_type=audio|stream_index=0|pts=194400|pts_time=2.160000|dts=194400|dts_time=2.160000|duration=1800|duration_time=0.020000|size=869|pos=106032|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=194400|pts_time=2.160000|dts=194400|dts_time=2.160000|duration=1800|duration_time=0.020000|size=869|pos=106032|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:263c4a83 -packet|codec_type=audio|stream_index=0|pts=196200|pts_time=2.180000|dts=196200|dts_time=2.180000|duration=1800|duration_time=0.020000|size=778|pos=106972|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=196200|pts_time=2.180000|dts=196200|dts_time=2.180000|duration=1800|duration_time=0.020000|size=778|pos=106972|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4017dc55 -packet|codec_type=audio|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=1800|duration_time=0.020000|size=777|pos=108288|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=1800|duration_time=0.020000|size=777|pos=108288|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e6b3c398 -packet|codec_type=audio|stream_index=0|pts=199800|pts_time=2.220000|dts=199800|dts_time=2.220000|duration=1800|duration_time=0.020000|size=870|pos=109228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=199800|pts_time=2.220000|dts=199800|dts_time=2.220000|duration=1800|duration_time=0.020000|size=870|pos=109228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:37eda28b -packet|codec_type=audio|stream_index=0|pts=201600|pts_time=2.240000|dts=201600|dts_time=2.240000|duration=1800|duration_time=0.020000|size=782|pos=110168|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=201600|pts_time=2.240000|dts=201600|dts_time=2.240000|duration=1800|duration_time=0.020000|size=782|pos=110168|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aa3b5d94 -packet|codec_type=audio|stream_index=0|pts=203400|pts_time=2.260000|dts=203400|dts_time=2.260000|duration=1800|duration_time=0.020000|size=777|pos=111108|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=203400|pts_time=2.260000|dts=203400|dts_time=2.260000|duration=1800|duration_time=0.020000|size=777|pos=111108|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fc87dbf0 -packet|codec_type=audio|stream_index=0|pts=205200|pts_time=2.280000|dts=205200|dts_time=2.280000|duration=1800|duration_time=0.020000|size=869|pos=112048|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=205200|pts_time=2.280000|dts=205200|dts_time=2.280000|duration=1800|duration_time=0.020000|size=869|pos=112048|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:75795b7e -packet|codec_type=audio|stream_index=0|pts=207000|pts_time=2.300000|dts=207000|dts_time=2.300000|duration=1800|duration_time=0.020000|size=772|pos=112988|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=207000|pts_time=2.300000|dts=207000|dts_time=2.300000|duration=1800|duration_time=0.020000|size=772|pos=112988|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a8a34bb9 -packet|codec_type=audio|stream_index=0|pts=208800|pts_time=2.320000|dts=208800|dts_time=2.320000|duration=1800|duration_time=0.020000|size=775|pos=113928|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=208800|pts_time=2.320000|dts=208800|dts_time=2.320000|duration=1800|duration_time=0.020000|size=775|pos=113928|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2ebc4e7b -packet|codec_type=audio|stream_index=0|pts=210600|pts_time=2.340000|dts=210600|dts_time=2.340000|duration=1800|duration_time=0.020000|size=771|pos=114868|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=210600|pts_time=2.340000|dts=210600|dts_time=2.340000|duration=1800|duration_time=0.020000|size=771|pos=114868|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:53744d32 -packet|codec_type=audio|stream_index=0|pts=212400|pts_time=2.360000|dts=212400|dts_time=2.360000|duration=1800|duration_time=0.020000|size=778|pos=115808|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=212400|pts_time=2.360000|dts=212400|dts_time=2.360000|duration=1800|duration_time=0.020000|size=778|pos=115808|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d32f77ce -packet|codec_type=audio|stream_index=0|pts=214200|pts_time=2.380000|dts=214200|dts_time=2.380000|duration=1800|duration_time=0.020000|size=867|pos=116748|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=214200|pts_time=2.380000|dts=214200|dts_time=2.380000|duration=1800|duration_time=0.020000|size=867|pos=116748|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f582287c -packet|codec_type=audio|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=1800|duration_time=0.020000|size=778|pos=118064|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=1800|duration_time=0.020000|size=778|pos=118064|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:144b9c4b -packet|codec_type=audio|stream_index=0|pts=217800|pts_time=2.420000|dts=217800|dts_time=2.420000|duration=1800|duration_time=0.020000|size=774|pos=119004|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=217800|pts_time=2.420000|dts=217800|dts_time=2.420000|duration=1800|duration_time=0.020000|size=774|pos=119004|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0cca881f -packet|codec_type=audio|stream_index=0|pts=219600|pts_time=2.440000|dts=219600|dts_time=2.440000|duration=1800|duration_time=0.020000|size=775|pos=119944|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=219600|pts_time=2.440000|dts=219600|dts_time=2.440000|duration=1800|duration_time=0.020000|size=775|pos=119944|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cddb1237 -packet|codec_type=audio|stream_index=0|pts=221400|pts_time=2.460000|dts=221400|dts_time=2.460000|duration=1800|duration_time=0.020000|size=774|pos=120884|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=221400|pts_time=2.460000|dts=221400|dts_time=2.460000|duration=1800|duration_time=0.020000|size=774|pos=120884|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:10310b68 -packet|codec_type=audio|stream_index=0|pts=223200|pts_time=2.480000|dts=223200|dts_time=2.480000|duration=1800|duration_time=0.020000|size=774|pos=121824|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=223200|pts_time=2.480000|dts=223200|dts_time=2.480000|duration=1800|duration_time=0.020000|size=774|pos=121824|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dea871f8 -packet|codec_type=audio|stream_index=0|pts=225000|pts_time=2.500000|dts=225000|dts_time=2.500000|duration=1800|duration_time=0.020000|size=772|pos=122764|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=225000|pts_time=2.500000|dts=225000|dts_time=2.500000|duration=1800|duration_time=0.020000|size=772|pos=122764|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d27e8c99 -packet|codec_type=audio|stream_index=0|pts=226800|pts_time=2.520000|dts=226800|dts_time=2.520000|duration=1800|duration_time=0.020000|size=774|pos=123704|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=226800|pts_time=2.520000|dts=226800|dts_time=2.520000|duration=1800|duration_time=0.020000|size=774|pos=123704|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3143b0e0 -packet|codec_type=audio|stream_index=0|pts=228600|pts_time=2.540000|dts=228600|dts_time=2.540000|duration=1800|duration_time=0.020000|size=775|pos=124644|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=228600|pts_time=2.540000|dts=228600|dts_time=2.540000|duration=1800|duration_time=0.020000|size=775|pos=124644|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ebc2c2e6 -packet|codec_type=audio|stream_index=0|pts=230400|pts_time=2.560000|dts=230400|dts_time=2.560000|duration=1800|duration_time=0.020000|size=773|pos=125584|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=230400|pts_time=2.560000|dts=230400|dts_time=2.560000|duration=1800|duration_time=0.020000|size=773|pos=125584|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dc63972d -packet|codec_type=audio|stream_index=0|pts=232200|pts_time=2.580000|dts=232200|dts_time=2.580000|duration=1800|duration_time=0.020000|size=773|pos=126524|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=232200|pts_time=2.580000|dts=232200|dts_time=2.580000|duration=1800|duration_time=0.020000|size=773|pos=126524|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6b141c19 -packet|codec_type=audio|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=1800|duration_time=0.020000|size=769|pos=127840|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=1800|duration_time=0.020000|size=769|pos=127840|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:752ada1e -packet|codec_type=audio|stream_index=0|pts=235800|pts_time=2.620000|dts=235800|dts_time=2.620000|duration=1800|duration_time=0.020000|size=774|pos=128780|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=235800|pts_time=2.620000|dts=235800|dts_time=2.620000|duration=1800|duration_time=0.020000|size=774|pos=128780|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:36d20d37 -packet|codec_type=audio|stream_index=0|pts=237600|pts_time=2.640000|dts=237600|dts_time=2.640000|duration=1800|duration_time=0.020000|size=779|pos=129720|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=237600|pts_time=2.640000|dts=237600|dts_time=2.640000|duration=1800|duration_time=0.020000|size=779|pos=129720|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1455dc2e -packet|codec_type=audio|stream_index=0|pts=239400|pts_time=2.660000|dts=239400|dts_time=2.660000|duration=1800|duration_time=0.020000|size=782|pos=130660|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=239400|pts_time=2.660000|dts=239400|dts_time=2.660000|duration=1800|duration_time=0.020000|size=782|pos=130660|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6ffd5fe -packet|codec_type=audio|stream_index=0|pts=241200|pts_time=2.680000|dts=241200|dts_time=2.680000|duration=1800|duration_time=0.020000|size=779|pos=131600|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=241200|pts_time=2.680000|dts=241200|dts_time=2.680000|duration=1800|duration_time=0.020000|size=779|pos=131600|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e4c83b97 -packet|codec_type=audio|stream_index=0|pts=243000|pts_time=2.700000|dts=243000|dts_time=2.700000|duration=1800|duration_time=0.020000|size=778|pos=132540|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=243000|pts_time=2.700000|dts=243000|dts_time=2.700000|duration=1800|duration_time=0.020000|size=778|pos=132540|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee3f9b5a -packet|codec_type=audio|stream_index=0|pts=244800|pts_time=2.720000|dts=244800|dts_time=2.720000|duration=1800|duration_time=0.020000|size=771|pos=133480|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=244800|pts_time=2.720000|dts=244800|dts_time=2.720000|duration=1800|duration_time=0.020000|size=771|pos=133480|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7d0ee8b4 -packet|codec_type=audio|stream_index=0|pts=246600|pts_time=2.740000|dts=246600|dts_time=2.740000|duration=1800|duration_time=0.020000|size=775|pos=134420|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=246600|pts_time=2.740000|dts=246600|dts_time=2.740000|duration=1800|duration_time=0.020000|size=775|pos=134420|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:685b64d8 -packet|codec_type=audio|stream_index=0|pts=248400|pts_time=2.760000|dts=248400|dts_time=2.760000|duration=1800|duration_time=0.020000|size=777|pos=135360|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=248400|pts_time=2.760000|dts=248400|dts_time=2.760000|duration=1800|duration_time=0.020000|size=777|pos=135360|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ab680b3f -packet|codec_type=audio|stream_index=0|pts=250200|pts_time=2.780000|dts=250200|dts_time=2.780000|duration=1800|duration_time=0.020000|size=773|pos=136300|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=250200|pts_time=2.780000|dts=250200|dts_time=2.780000|duration=1800|duration_time=0.020000|size=773|pos=136300|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8485bf04 -packet|codec_type=audio|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=1800|duration_time=0.020000|size=777|pos=137616|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=1800|duration_time=0.020000|size=777|pos=137616|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:60e3ab3b -packet|codec_type=audio|stream_index=0|pts=253800|pts_time=2.820000|dts=253800|dts_time=2.820000|duration=1800|duration_time=0.020000|size=777|pos=138556|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=253800|pts_time=2.820000|dts=253800|dts_time=2.820000|duration=1800|duration_time=0.020000|size=777|pos=138556|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cbacc337 -packet|codec_type=audio|stream_index=0|pts=255600|pts_time=2.840000|dts=255600|dts_time=2.840000|duration=1800|duration_time=0.020000|size=908|pos=139496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=255600|pts_time=2.840000|dts=255600|dts_time=2.840000|duration=1800|duration_time=0.020000|size=908|pos=139496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:852be5a3 -packet|codec_type=audio|stream_index=0|pts=257400|pts_time=2.860000|dts=257400|dts_time=2.860000|duration=1800|duration_time=0.020000|size=777|pos=140624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=257400|pts_time=2.860000|dts=257400|dts_time=2.860000|duration=1800|duration_time=0.020000|size=777|pos=140624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:743f04a8 -packet|codec_type=audio|stream_index=0|pts=259200|pts_time=2.880000|dts=259200|dts_time=2.880000|duration=1800|duration_time=0.020000|size=772|pos=141564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=259200|pts_time=2.880000|dts=259200|dts_time=2.880000|duration=1800|duration_time=0.020000|size=772|pos=141564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0ed88196 -packet|codec_type=audio|stream_index=0|pts=261000|pts_time=2.900000|dts=261000|dts_time=2.900000|duration=1800|duration_time=0.020000|size=778|pos=142504|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=261000|pts_time=2.900000|dts=261000|dts_time=2.900000|duration=1800|duration_time=0.020000|size=778|pos=142504|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bf13126e -packet|codec_type=audio|stream_index=0|pts=262800|pts_time=2.920000|dts=262800|dts_time=2.920000|duration=1800|duration_time=0.020000|size=776|pos=143444|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=262800|pts_time=2.920000|dts=262800|dts_time=2.920000|duration=1800|duration_time=0.020000|size=776|pos=143444|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dd160d29 -packet|codec_type=audio|stream_index=0|pts=264600|pts_time=2.940000|dts=264600|dts_time=2.940000|duration=1800|duration_time=0.020000|size=775|pos=144384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=264600|pts_time=2.940000|dts=264600|dts_time=2.940000|duration=1800|duration_time=0.020000|size=775|pos=144384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:65833aa7 -packet|codec_type=audio|stream_index=0|pts=266400|pts_time=2.960000|dts=266400|dts_time=2.960000|duration=1800|duration_time=0.020000|size=772|pos=145324|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=266400|pts_time=2.960000|dts=266400|dts_time=2.960000|duration=1800|duration_time=0.020000|size=772|pos=145324|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9343d3d2 -packet|codec_type=audio|stream_index=0|pts=268200|pts_time=2.980000|dts=268200|dts_time=2.980000|duration=1800|duration_time=0.020000|size=778|pos=146264|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=268200|pts_time=2.980000|dts=268200|dts_time=2.980000|duration=1800|duration_time=0.020000|size=778|pos=146264|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7da0cd8d -packet|codec_type=audio|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=1800|duration_time=0.020000|size=808|pos=147580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=1800|duration_time=0.020000|size=808|pos=147580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8a3298b7 -packet|codec_type=audio|stream_index=0|pts=271800|pts_time=3.020000|dts=271800|dts_time=3.020000|duration=1800|duration_time=0.020000|size=836|pos=148520|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=271800|pts_time=3.020000|dts=271800|dts_time=3.020000|duration=1800|duration_time=0.020000|size=836|pos=148520|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:604d40c4 -packet|codec_type=audio|stream_index=0|pts=273600|pts_time=3.040000|dts=273600|dts_time=3.040000|duration=1800|duration_time=0.020000|size=913|pos=149460|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=273600|pts_time=3.040000|dts=273600|dts_time=3.040000|duration=1800|duration_time=0.020000|size=913|pos=149460|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ecd7b491 -packet|codec_type=audio|stream_index=0|pts=275400|pts_time=3.060000|dts=275400|dts_time=3.060000|duration=1800|duration_time=0.020000|size=837|pos=150588|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=275400|pts_time=3.060000|dts=275400|dts_time=3.060000|duration=1800|duration_time=0.020000|size=837|pos=150588|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f8907616 -packet|codec_type=audio|stream_index=0|pts=277200|pts_time=3.080000|dts=277200|dts_time=3.080000|duration=1800|duration_time=0.020000|size=834|pos=151528|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=277200|pts_time=3.080000|dts=277200|dts_time=3.080000|duration=1800|duration_time=0.020000|size=834|pos=151528|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6701edc -packet|codec_type=audio|stream_index=0|pts=279000|pts_time=3.100000|dts=279000|dts_time=3.100000|duration=1800|duration_time=0.020000|size=836|pos=152468|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=279000|pts_time=3.100000|dts=279000|dts_time=3.100000|duration=1800|duration_time=0.020000|size=836|pos=152468|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ed85bdee -packet|codec_type=audio|stream_index=0|pts=280800|pts_time=3.120000|dts=280800|dts_time=3.120000|duration=1800|duration_time=0.020000|size=832|pos=153408|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=280800|pts_time=3.120000|dts=280800|dts_time=3.120000|duration=1800|duration_time=0.020000|size=832|pos=153408|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d9ea8517 -packet|codec_type=audio|stream_index=0|pts=282600|pts_time=3.140000|dts=282600|dts_time=3.140000|duration=1800|duration_time=0.020000|size=826|pos=154348|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=282600|pts_time=3.140000|dts=282600|dts_time=3.140000|duration=1800|duration_time=0.020000|size=826|pos=154348|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e396092f -packet|codec_type=audio|stream_index=0|pts=284400|pts_time=3.160000|dts=284400|dts_time=3.160000|duration=1800|duration_time=0.020000|size=817|pos=155288|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=284400|pts_time=3.160000|dts=284400|dts_time=3.160000|duration=1800|duration_time=0.020000|size=817|pos=155288|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1c628f31 -packet|codec_type=audio|stream_index=0|pts=286200|pts_time=3.180000|dts=286200|dts_time=3.180000|duration=1800|duration_time=0.020000|size=825|pos=156228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=286200|pts_time=3.180000|dts=286200|dts_time=3.180000|duration=1800|duration_time=0.020000|size=825|pos=156228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:52183b8f -packet|codec_type=audio|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=1800|duration_time=0.020000|size=824|pos=157544|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=1800|duration_time=0.020000|size=824|pos=157544|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bbae2882 -packet|codec_type=audio|stream_index=0|pts=289800|pts_time=3.220000|dts=289800|dts_time=3.220000|duration=1800|duration_time=0.020000|size=828|pos=158484|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=289800|pts_time=3.220000|dts=289800|dts_time=3.220000|duration=1800|duration_time=0.020000|size=828|pos=158484|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bb5a7486 -packet|codec_type=audio|stream_index=0|pts=291600|pts_time=3.240000|dts=291600|dts_time=3.240000|duration=1800|duration_time=0.020000|size=833|pos=159424|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=291600|pts_time=3.240000|dts=291600|dts_time=3.240000|duration=1800|duration_time=0.020000|size=833|pos=159424|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ead8306a -packet|codec_type=audio|stream_index=0|pts=293400|pts_time=3.260000|dts=293400|dts_time=3.260000|duration=1800|duration_time=0.020000|size=832|pos=160364|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=293400|pts_time=3.260000|dts=293400|dts_time=3.260000|duration=1800|duration_time=0.020000|size=832|pos=160364|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:82db1098 -packet|codec_type=audio|stream_index=0|pts=295200|pts_time=3.280000|dts=295200|dts_time=3.280000|duration=1800|duration_time=0.020000|size=896|pos=161304|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=295200|pts_time=3.280000|dts=295200|dts_time=3.280000|duration=1800|duration_time=0.020000|size=896|pos=161304|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:688f5cb6 -packet|codec_type=audio|stream_index=0|pts=297000|pts_time=3.300000|dts=297000|dts_time=3.300000|duration=1800|duration_time=0.020000|size=824|pos=162244|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=297000|pts_time=3.300000|dts=297000|dts_time=3.300000|duration=1800|duration_time=0.020000|size=824|pos=162244|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fdf34c0b -packet|codec_type=audio|stream_index=0|pts=298800|pts_time=3.320000|dts=298800|dts_time=3.320000|duration=1800|duration_time=0.020000|size=812|pos=163184|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=298800|pts_time=3.320000|dts=298800|dts_time=3.320000|duration=1800|duration_time=0.020000|size=812|pos=163184|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:802e95d1 -packet|codec_type=audio|stream_index=0|pts=300600|pts_time=3.340000|dts=300600|dts_time=3.340000|duration=1800|duration_time=0.020000|size=821|pos=164124|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=300600|pts_time=3.340000|dts=300600|dts_time=3.340000|duration=1800|duration_time=0.020000|size=821|pos=164124|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:141404b8 -packet|codec_type=audio|stream_index=0|pts=302400|pts_time=3.360000|dts=302400|dts_time=3.360000|duration=1800|duration_time=0.020000|size=883|pos=165064|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=302400|pts_time=3.360000|dts=302400|dts_time=3.360000|duration=1800|duration_time=0.020000|size=883|pos=165064|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3e39e373 -packet|codec_type=audio|stream_index=0|pts=304200|pts_time=3.380000|dts=304200|dts_time=3.380000|duration=1800|duration_time=0.020000|size=820|pos=166004|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=304200|pts_time=3.380000|dts=304200|dts_time=3.380000|duration=1800|duration_time=0.020000|size=820|pos=166004|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ce8d8234 -packet|codec_type=audio|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=1800|duration_time=0.020000|size=835|pos=167320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=1800|duration_time=0.020000|size=835|pos=167320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0f3c194d -packet|codec_type=audio|stream_index=0|pts=307800|pts_time=3.420000|dts=307800|dts_time=3.420000|duration=1800|duration_time=0.020000|size=833|pos=168260|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=307800|pts_time=3.420000|dts=307800|dts_time=3.420000|duration=1800|duration_time=0.020000|size=833|pos=168260|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3d5d60c4 -packet|codec_type=audio|stream_index=0|pts=309600|pts_time=3.440000|dts=309600|dts_time=3.440000|duration=1800|duration_time=0.020000|size=830|pos=169200|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=309600|pts_time=3.440000|dts=309600|dts_time=3.440000|duration=1800|duration_time=0.020000|size=830|pos=169200|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f66b2c9f -packet|codec_type=audio|stream_index=0|pts=311400|pts_time=3.460000|dts=311400|dts_time=3.460000|duration=1800|duration_time=0.020000|size=820|pos=170140|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=311400|pts_time=3.460000|dts=311400|dts_time=3.460000|duration=1800|duration_time=0.020000|size=820|pos=170140|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:44eb2398 -packet|codec_type=audio|stream_index=0|pts=313200|pts_time=3.480000|dts=313200|dts_time=3.480000|duration=1800|duration_time=0.020000|size=815|pos=171080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=313200|pts_time=3.480000|dts=313200|dts_time=3.480000|duration=1800|duration_time=0.020000|size=815|pos=171080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cec1f69c -packet|codec_type=audio|stream_index=0|pts=315000|pts_time=3.500000|dts=315000|dts_time=3.500000|duration=1800|duration_time=0.020000|size=827|pos=172020|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=315000|pts_time=3.500000|dts=315000|dts_time=3.500000|duration=1800|duration_time=0.020000|size=827|pos=172020|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57096eb1 -packet|codec_type=audio|stream_index=0|pts=316800|pts_time=3.520000|dts=316800|dts_time=3.520000|duration=1800|duration_time=0.020000|size=819|pos=172960|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=316800|pts_time=3.520000|dts=316800|dts_time=3.520000|duration=1800|duration_time=0.020000|size=819|pos=172960|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:66999a29 -packet|codec_type=audio|stream_index=0|pts=318600|pts_time=3.540000|dts=318600|dts_time=3.540000|duration=1800|duration_time=0.020000|size=828|pos=173900|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=318600|pts_time=3.540000|dts=318600|dts_time=3.540000|duration=1800|duration_time=0.020000|size=828|pos=173900|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0e598023 -packet|codec_type=audio|stream_index=0|pts=320400|pts_time=3.560000|dts=320400|dts_time=3.560000|duration=1800|duration_time=0.020000|size=830|pos=174840|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=320400|pts_time=3.560000|dts=320400|dts_time=3.560000|duration=1800|duration_time=0.020000|size=830|pos=174840|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8e728d2b -packet|codec_type=audio|stream_index=0|pts=322200|pts_time=3.580000|dts=322200|dts_time=3.580000|duration=1800|duration_time=0.020000|size=828|pos=175780|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=322200|pts_time=3.580000|dts=322200|dts_time=3.580000|duration=1800|duration_time=0.020000|size=828|pos=175780|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7e7549e3 -packet|codec_type=audio|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=1800|duration_time=0.020000|size=829|pos=177096|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=1800|duration_time=0.020000|size=829|pos=177096|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:62f96c18 -packet|codec_type=audio|stream_index=0|pts=325800|pts_time=3.620000|dts=325800|dts_time=3.620000|duration=1800|duration_time=0.020000|size=820|pos=178036|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=325800|pts_time=3.620000|dts=325800|dts_time=3.620000|duration=1800|duration_time=0.020000|size=820|pos=178036|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:48d04b8a -packet|codec_type=audio|stream_index=0|pts=327600|pts_time=3.640000|dts=327600|dts_time=3.640000|duration=1800|duration_time=0.020000|size=823|pos=178976|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=327600|pts_time=3.640000|dts=327600|dts_time=3.640000|duration=1800|duration_time=0.020000|size=823|pos=178976|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7937563e -packet|codec_type=audio|stream_index=0|pts=329400|pts_time=3.660000|dts=329400|dts_time=3.660000|duration=1800|duration_time=0.020000|size=798|pos=179916|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=329400|pts_time=3.660000|dts=329400|dts_time=3.660000|duration=1800|duration_time=0.020000|size=798|pos=179916|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8e573ad0 -packet|codec_type=audio|stream_index=0|pts=331200|pts_time=3.680000|dts=331200|dts_time=3.680000|duration=1800|duration_time=0.020000|size=772|pos=180856|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=331200|pts_time=3.680000|dts=331200|dts_time=3.680000|duration=1800|duration_time=0.020000|size=772|pos=180856|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ece4d7e7 -packet|codec_type=audio|stream_index=0|pts=333000|pts_time=3.700000|dts=333000|dts_time=3.700000|duration=1800|duration_time=0.020000|size=779|pos=181796|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=333000|pts_time=3.700000|dts=333000|dts_time=3.700000|duration=1800|duration_time=0.020000|size=779|pos=181796|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4ca26e7d -packet|codec_type=audio|stream_index=0|pts=334800|pts_time=3.720000|dts=334800|dts_time=3.720000|duration=1800|duration_time=0.020000|size=774|pos=182736|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=334800|pts_time=3.720000|dts=334800|dts_time=3.720000|duration=1800|duration_time=0.020000|size=774|pos=182736|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8c347b2d -packet|codec_type=audio|stream_index=0|pts=336600|pts_time=3.740000|dts=336600|dts_time=3.740000|duration=1800|duration_time=0.020000|size=907|pos=183676|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=336600|pts_time=3.740000|dts=336600|dts_time=3.740000|duration=1800|duration_time=0.020000|size=907|pos=183676|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b50e55b8 -packet|codec_type=audio|stream_index=0|pts=338400|pts_time=3.760000|dts=338400|dts_time=3.760000|duration=1800|duration_time=0.020000|size=772|pos=184804|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=338400|pts_time=3.760000|dts=338400|dts_time=3.760000|duration=1800|duration_time=0.020000|size=772|pos=184804|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e2ff539f -packet|codec_type=audio|stream_index=0|pts=340200|pts_time=3.780000|dts=340200|dts_time=3.780000|duration=1800|duration_time=0.020000|size=777|pos=185744|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=340200|pts_time=3.780000|dts=340200|dts_time=3.780000|duration=1800|duration_time=0.020000|size=777|pos=185744|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f86e1c5a -packet|codec_type=audio|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=1800|duration_time=0.020000|size=777|pos=187060|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=1800|duration_time=0.020000|size=777|pos=187060|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ff858811 -packet|codec_type=audio|stream_index=0|pts=343800|pts_time=3.820000|dts=343800|dts_time=3.820000|duration=1800|duration_time=0.020000|size=777|pos=188000|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=343800|pts_time=3.820000|dts=343800|dts_time=3.820000|duration=1800|duration_time=0.020000|size=777|pos=188000|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4b0da83e -packet|codec_type=audio|stream_index=0|pts=345600|pts_time=3.840000|dts=345600|dts_time=3.840000|duration=1800|duration_time=0.020000|size=775|pos=188940|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=345600|pts_time=3.840000|dts=345600|dts_time=3.840000|duration=1800|duration_time=0.020000|size=775|pos=188940|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:605a41a9 -packet|codec_type=audio|stream_index=0|pts=347400|pts_time=3.860000|dts=347400|dts_time=3.860000|duration=1800|duration_time=0.020000|size=773|pos=189880|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=347400|pts_time=3.860000|dts=347400|dts_time=3.860000|duration=1800|duration_time=0.020000|size=773|pos=189880|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d32c5756 -packet|codec_type=audio|stream_index=0|pts=349200|pts_time=3.880000|dts=349200|dts_time=3.880000|duration=1800|duration_time=0.020000|size=777|pos=190820|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=349200|pts_time=3.880000|dts=349200|dts_time=3.880000|duration=1800|duration_time=0.020000|size=777|pos=190820|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:92c557ef -packet|codec_type=audio|stream_index=0|pts=351000|pts_time=3.900000|dts=351000|dts_time=3.900000|duration=1800|duration_time=0.020000|size=777|pos=191760|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=351000|pts_time=3.900000|dts=351000|dts_time=3.900000|duration=1800|duration_time=0.020000|size=777|pos=191760|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c16056ca -packet|codec_type=audio|stream_index=0|pts=352800|pts_time=3.920000|dts=352800|dts_time=3.920000|duration=1800|duration_time=0.020000|size=776|pos=192700|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=352800|pts_time=3.920000|dts=352800|dts_time=3.920000|duration=1800|duration_time=0.020000|size=776|pos=192700|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c84a2e99 -packet|codec_type=audio|stream_index=0|pts=354600|pts_time=3.940000|dts=354600|dts_time=3.940000|duration=1800|duration_time=0.020000|size=780|pos=193640|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=354600|pts_time=3.940000|dts=354600|dts_time=3.940000|duration=1800|duration_time=0.020000|size=780|pos=193640|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d59309d0 -packet|codec_type=audio|stream_index=0|pts=356400|pts_time=3.960000|dts=356400|dts_time=3.960000|duration=1800|duration_time=0.020000|size=776|pos=194580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=356400|pts_time=3.960000|dts=356400|dts_time=3.960000|duration=1800|duration_time=0.020000|size=776|pos=194580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8312e1ba -packet|codec_type=audio|stream_index=0|pts=358200|pts_time=3.980000|dts=358200|dts_time=3.980000|duration=1800|duration_time=0.020000|size=778|pos=195520|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=358200|pts_time=3.980000|dts=358200|dts_time=3.980000|duration=1800|duration_time=0.020000|size=778|pos=195520|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:12d77a3e -packet|codec_type=audio|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=1800|duration_time=0.020000|size=774|pos=196836|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=1800|duration_time=0.020000|size=774|pos=196836|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:86b417d4 -packet|codec_type=audio|stream_index=0|pts=361800|pts_time=4.020000|dts=361800|dts_time=4.020000|duration=1800|duration_time=0.020000|size=778|pos=197776|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=361800|pts_time=4.020000|dts=361800|dts_time=4.020000|duration=1800|duration_time=0.020000|size=778|pos=197776|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a66ed4cf -packet|codec_type=audio|stream_index=0|pts=363600|pts_time=4.040000|dts=363600|dts_time=4.040000|duration=1800|duration_time=0.020000|size=777|pos=198716|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=363600|pts_time=4.040000|dts=363600|dts_time=4.040000|duration=1800|duration_time=0.020000|size=777|pos=198716|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b686a5ca -packet|codec_type=audio|stream_index=0|pts=365400|pts_time=4.060000|dts=365400|dts_time=4.060000|duration=1800|duration_time=0.020000|size=773|pos=199656|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=365400|pts_time=4.060000|dts=365400|dts_time=4.060000|duration=1800|duration_time=0.020000|size=773|pos=199656|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:261ce45b -packet|codec_type=audio|stream_index=0|pts=367200|pts_time=4.080000|dts=367200|dts_time=4.080000|duration=1800|duration_time=0.020000|size=782|pos=200596|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=367200|pts_time=4.080000|dts=367200|dts_time=4.080000|duration=1800|duration_time=0.020000|size=782|pos=200596|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cbfbd1bf -packet|codec_type=audio|stream_index=0|pts=369000|pts_time=4.100000|dts=369000|dts_time=4.100000|duration=1800|duration_time=0.020000|size=780|pos=201536|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=369000|pts_time=4.100000|dts=369000|dts_time=4.100000|duration=1800|duration_time=0.020000|size=780|pos=201536|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:20b5484f -packet|codec_type=audio|stream_index=0|pts=370800|pts_time=4.120000|dts=370800|dts_time=4.120000|duration=1800|duration_time=0.020000|size=777|pos=202476|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=370800|pts_time=4.120000|dts=370800|dts_time=4.120000|duration=1800|duration_time=0.020000|size=777|pos=202476|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c4d54099 -packet|codec_type=audio|stream_index=0|pts=372600|pts_time=4.140000|dts=372600|dts_time=4.140000|duration=1800|duration_time=0.020000|size=775|pos=203416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=372600|pts_time=4.140000|dts=372600|dts_time=4.140000|duration=1800|duration_time=0.020000|size=775|pos=203416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cb665fdf -packet|codec_type=audio|stream_index=0|pts=374400|pts_time=4.160000|dts=374400|dts_time=4.160000|duration=1800|duration_time=0.020000|size=777|pos=204356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=374400|pts_time=4.160000|dts=374400|dts_time=4.160000|duration=1800|duration_time=0.020000|size=777|pos=204356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0271ab1f -packet|codec_type=audio|stream_index=0|pts=376200|pts_time=4.180000|dts=376200|dts_time=4.180000|duration=1800|duration_time=0.020000|size=776|pos=205296|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=376200|pts_time=4.180000|dts=376200|dts_time=4.180000|duration=1800|duration_time=0.020000|size=776|pos=205296|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a82f4ab4 -packet|codec_type=audio|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=1800|duration_time=0.020000|size=778|pos=206612|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=1800|duration_time=0.020000|size=778|pos=206612|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a1e09e3b -packet|codec_type=audio|stream_index=0|pts=379800|pts_time=4.220000|dts=379800|dts_time=4.220000|duration=1800|duration_time=0.020000|size=775|pos=207552|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=379800|pts_time=4.220000|dts=379800|dts_time=4.220000|duration=1800|duration_time=0.020000|size=775|pos=207552|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7b297a73 -packet|codec_type=audio|stream_index=0|pts=381600|pts_time=4.240000|dts=381600|dts_time=4.240000|duration=1800|duration_time=0.020000|size=775|pos=208492|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=381600|pts_time=4.240000|dts=381600|dts_time=4.240000|duration=1800|duration_time=0.020000|size=775|pos=208492|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2165ebef -packet|codec_type=audio|stream_index=0|pts=383400|pts_time=4.260000|dts=383400|dts_time=4.260000|duration=1800|duration_time=0.020000|size=779|pos=209432|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=383400|pts_time=4.260000|dts=383400|dts_time=4.260000|duration=1800|duration_time=0.020000|size=779|pos=209432|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b802ae36 -packet|codec_type=audio|stream_index=0|pts=385200|pts_time=4.280000|dts=385200|dts_time=4.280000|duration=1800|duration_time=0.020000|size=779|pos=210372|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=385200|pts_time=4.280000|dts=385200|dts_time=4.280000|duration=1800|duration_time=0.020000|size=779|pos=210372|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:36ca4657 -packet|codec_type=audio|stream_index=0|pts=387000|pts_time=4.300000|dts=387000|dts_time=4.300000|duration=1800|duration_time=0.020000|size=778|pos=211312|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=387000|pts_time=4.300000|dts=387000|dts_time=4.300000|duration=1800|duration_time=0.020000|size=778|pos=211312|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2fe8a70c -packet|codec_type=audio|stream_index=0|pts=388800|pts_time=4.320000|dts=388800|dts_time=4.320000|duration=1800|duration_time=0.020000|size=780|pos=212252|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=388800|pts_time=4.320000|dts=388800|dts_time=4.320000|duration=1800|duration_time=0.020000|size=780|pos=212252|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:19c3bc8c -packet|codec_type=audio|stream_index=0|pts=390600|pts_time=4.340000|dts=390600|dts_time=4.340000|duration=1800|duration_time=0.020000|size=778|pos=213192|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=390600|pts_time=4.340000|dts=390600|dts_time=4.340000|duration=1800|duration_time=0.020000|size=778|pos=213192|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3b6c08d8 -packet|codec_type=audio|stream_index=0|pts=392400|pts_time=4.360000|dts=392400|dts_time=4.360000|duration=1800|duration_time=0.020000|size=776|pos=214132|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=392400|pts_time=4.360000|dts=392400|dts_time=4.360000|duration=1800|duration_time=0.020000|size=776|pos=214132|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:851471f3 -packet|codec_type=audio|stream_index=0|pts=394200|pts_time=4.380000|dts=394200|dts_time=4.380000|duration=1800|duration_time=0.020000|size=777|pos=215072|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=394200|pts_time=4.380000|dts=394200|dts_time=4.380000|duration=1800|duration_time=0.020000|size=777|pos=215072|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5d33a166 -packet|codec_type=audio|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=1800|duration_time=0.020000|size=841|pos=216388|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=1800|duration_time=0.020000|size=841|pos=216388|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d0d1a21b -packet|codec_type=audio|stream_index=0|pts=397800|pts_time=4.420000|dts=397800|dts_time=4.420000|duration=1800|duration_time=0.020000|size=777|pos=217328|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=397800|pts_time=4.420000|dts=397800|dts_time=4.420000|duration=1800|duration_time=0.020000|size=777|pos=217328|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c21a3376 -packet|codec_type=audio|stream_index=0|pts=399600|pts_time=4.440000|dts=399600|dts_time=4.440000|duration=1800|duration_time=0.020000|size=780|pos=218268|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=399600|pts_time=4.440000|dts=399600|dts_time=4.440000|duration=1800|duration_time=0.020000|size=780|pos=218268|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0daaead6 -packet|codec_type=audio|stream_index=0|pts=401400|pts_time=4.460000|dts=401400|dts_time=4.460000|duration=1800|duration_time=0.020000|size=777|pos=219208|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=401400|pts_time=4.460000|dts=401400|dts_time=4.460000|duration=1800|duration_time=0.020000|size=777|pos=219208|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:01c07956 -packet|codec_type=audio|stream_index=0|pts=403200|pts_time=4.480000|dts=403200|dts_time=4.480000|duration=1800|duration_time=0.020000|size=777|pos=220148|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=403200|pts_time=4.480000|dts=403200|dts_time=4.480000|duration=1800|duration_time=0.020000|size=777|pos=220148|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f5b429c1 -packet|codec_type=audio|stream_index=0|pts=405000|pts_time=4.500000|dts=405000|dts_time=4.500000|duration=1800|duration_time=0.020000|size=778|pos=221088|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=405000|pts_time=4.500000|dts=405000|dts_time=4.500000|duration=1800|duration_time=0.020000|size=778|pos=221088|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a46831d9 -packet|codec_type=audio|stream_index=0|pts=406800|pts_time=4.520000|dts=406800|dts_time=4.520000|duration=1800|duration_time=0.020000|size=778|pos=222028|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=406800|pts_time=4.520000|dts=406800|dts_time=4.520000|duration=1800|duration_time=0.020000|size=778|pos=222028|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:555d2cb1 -packet|codec_type=audio|stream_index=0|pts=408600|pts_time=4.540000|dts=408600|dts_time=4.540000|duration=1800|duration_time=0.020000|size=779|pos=222968|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=408600|pts_time=4.540000|dts=408600|dts_time=4.540000|duration=1800|duration_time=0.020000|size=779|pos=222968|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7670785c -packet|codec_type=audio|stream_index=0|pts=410400|pts_time=4.560000|dts=410400|dts_time=4.560000|duration=1800|duration_time=0.020000|size=776|pos=223908|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=410400|pts_time=4.560000|dts=410400|dts_time=4.560000|duration=1800|duration_time=0.020000|size=776|pos=223908|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:52a244cd -packet|codec_type=audio|stream_index=0|pts=412200|pts_time=4.580000|dts=412200|dts_time=4.580000|duration=1800|duration_time=0.020000|size=784|pos=224848|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=412200|pts_time=4.580000|dts=412200|dts_time=4.580000|duration=1800|duration_time=0.020000|size=784|pos=224848|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7ad67c41 -packet|codec_type=audio|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=1800|duration_time=0.020000|size=776|pos=226164|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=1800|duration_time=0.020000|size=776|pos=226164|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ddc7990b -packet|codec_type=audio|stream_index=0|pts=415800|pts_time=4.620000|dts=415800|dts_time=4.620000|duration=1800|duration_time=0.020000|size=778|pos=227104|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=415800|pts_time=4.620000|dts=415800|dts_time=4.620000|duration=1800|duration_time=0.020000|size=778|pos=227104|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8a49bff6 -packet|codec_type=audio|stream_index=0|pts=417600|pts_time=4.640000|dts=417600|dts_time=4.640000|duration=1800|duration_time=0.020000|size=775|pos=228044|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=417600|pts_time=4.640000|dts=417600|dts_time=4.640000|duration=1800|duration_time=0.020000|size=775|pos=228044|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:258dc60a -packet|codec_type=audio|stream_index=0|pts=419400|pts_time=4.660000|dts=419400|dts_time=4.660000|duration=1800|duration_time=0.020000|size=781|pos=228984|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=419400|pts_time=4.660000|dts=419400|dts_time=4.660000|duration=1800|duration_time=0.020000|size=781|pos=228984|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2dd6d159 -packet|codec_type=audio|stream_index=0|pts=421200|pts_time=4.680000|dts=421200|dts_time=4.680000|duration=1800|duration_time=0.020000|size=779|pos=229924|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=421200|pts_time=4.680000|dts=421200|dts_time=4.680000|duration=1800|duration_time=0.020000|size=779|pos=229924|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:359ba790 -packet|codec_type=audio|stream_index=0|pts=423000|pts_time=4.700000|dts=423000|dts_time=4.700000|duration=1800|duration_time=0.020000|size=846|pos=230864|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=423000|pts_time=4.700000|dts=423000|dts_time=4.700000|duration=1800|duration_time=0.020000|size=846|pos=230864|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:68cbef69 -packet|codec_type=audio|stream_index=0|pts=424800|pts_time=4.720000|dts=424800|dts_time=4.720000|duration=1800|duration_time=0.020000|size=776|pos=231804|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=424800|pts_time=4.720000|dts=424800|dts_time=4.720000|duration=1800|duration_time=0.020000|size=776|pos=231804|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cbce1c41 -packet|codec_type=audio|stream_index=0|pts=426600|pts_time=4.740000|dts=426600|dts_time=4.740000|duration=1800|duration_time=0.020000|size=781|pos=232744|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=426600|pts_time=4.740000|dts=426600|dts_time=4.740000|duration=1800|duration_time=0.020000|size=781|pos=232744|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9a19b23 -packet|codec_type=audio|stream_index=0|pts=428400|pts_time=4.760000|dts=428400|dts_time=4.760000|duration=1800|duration_time=0.020000|size=783|pos=233684|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=428400|pts_time=4.760000|dts=428400|dts_time=4.760000|duration=1800|duration_time=0.020000|size=783|pos=233684|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f31b8def -packet|codec_type=audio|stream_index=0|pts=430200|pts_time=4.780000|dts=430200|dts_time=4.780000|duration=1800|duration_time=0.020000|size=971|pos=234624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=430200|pts_time=4.780000|dts=430200|dts_time=4.780000|duration=1800|duration_time=0.020000|size=971|pos=234624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4dd92879 -packet|codec_type=audio|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=1800|duration_time=0.020000|size=970|pos=236128|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=1800|duration_time=0.020000|size=970|pos=236128|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7020e4a7 -packet|codec_type=audio|stream_index=0|pts=433800|pts_time=4.820000|dts=433800|dts_time=4.820000|duration=1800|duration_time=0.020000|size=967|pos=237256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=433800|pts_time=4.820000|dts=433800|dts_time=4.820000|duration=1800|duration_time=0.020000|size=967|pos=237256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5f56efad -packet|codec_type=audio|stream_index=0|pts=435600|pts_time=4.840000|dts=435600|dts_time=4.840000|duration=1800|duration_time=0.020000|size=776|pos=238384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=435600|pts_time=4.840000|dts=435600|dts_time=4.840000|duration=1800|duration_time=0.020000|size=776|pos=238384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4ae7101d -packet|codec_type=audio|stream_index=0|pts=437400|pts_time=4.860000|dts=437400|dts_time=4.860000|duration=1800|duration_time=0.020000|size=971|pos=239324|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=437400|pts_time=4.860000|dts=437400|dts_time=4.860000|duration=1800|duration_time=0.020000|size=971|pos=239324|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:386c5965 -packet|codec_type=audio|stream_index=0|pts=439200|pts_time=4.880000|dts=439200|dts_time=4.880000|duration=1800|duration_time=0.020000|size=962|pos=240452|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=439200|pts_time=4.880000|dts=439200|dts_time=4.880000|duration=1800|duration_time=0.020000|size=962|pos=240452|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f2701022 -packet|codec_type=audio|stream_index=0|pts=441000|pts_time=4.900000|dts=441000|dts_time=4.900000|duration=1800|duration_time=0.020000|size=964|pos=241580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=441000|pts_time=4.900000|dts=441000|dts_time=4.900000|duration=1800|duration_time=0.020000|size=964|pos=241580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:386bfd07 -packet|codec_type=audio|stream_index=0|pts=442800|pts_time=4.920000|dts=442800|dts_time=4.920000|duration=1800|duration_time=0.020000|size=773|pos=242708|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=442800|pts_time=4.920000|dts=442800|dts_time=4.920000|duration=1800|duration_time=0.020000|size=773|pos=242708|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:080e4345 -packet|codec_type=audio|stream_index=0|pts=444600|pts_time=4.940000|dts=444600|dts_time=4.940000|duration=1800|duration_time=0.020000|size=770|pos=243648|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=444600|pts_time=4.940000|dts=444600|dts_time=4.940000|duration=1800|duration_time=0.020000|size=770|pos=243648|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4fbaa6b9 -packet|codec_type=audio|stream_index=0|pts=446400|pts_time=4.960000|dts=446400|dts_time=4.960000|duration=1800|duration_time=0.020000|size=964|pos=244588|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=446400|pts_time=4.960000|dts=446400|dts_time=4.960000|duration=1800|duration_time=0.020000|size=964|pos=244588|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5c879539 -packet|codec_type=audio|stream_index=0|pts=448200|pts_time=4.980000|dts=448200|dts_time=4.980000|duration=1800|duration_time=0.020000|size=958|pos=245716|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=448200|pts_time=4.980000|dts=448200|dts_time=4.980000|duration=1800|duration_time=0.020000|size=958|pos=245716|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dac40562 -packet|codec_type=audio|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=1800|duration_time=0.020000|size=775|pos=247220|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=1800|duration_time=0.020000|size=775|pos=247220|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:31f989e0 -packet|codec_type=audio|stream_index=0|pts=451800|pts_time=5.020000|dts=451800|dts_time=5.020000|duration=1800|duration_time=0.020000|size=775|pos=248160|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=451800|pts_time=5.020000|dts=451800|dts_time=5.020000|duration=1800|duration_time=0.020000|size=775|pos=248160|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0149cc11 -packet|codec_type=audio|stream_index=0|pts=453600|pts_time=5.040000|dts=453600|dts_time=5.040000|duration=1800|duration_time=0.020000|size=966|pos=249100|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=453600|pts_time=5.040000|dts=453600|dts_time=5.040000|duration=1800|duration_time=0.020000|size=966|pos=249100|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1c226514 -packet|codec_type=audio|stream_index=0|pts=455400|pts_time=5.060000|dts=455400|dts_time=5.060000|duration=1800|duration_time=0.020000|size=843|pos=250228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=455400|pts_time=5.060000|dts=455400|dts_time=5.060000|duration=1800|duration_time=0.020000|size=843|pos=250228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:991ab49b -packet|codec_type=audio|stream_index=0|pts=457200|pts_time=5.080000|dts=457200|dts_time=5.080000|duration=1800|duration_time=0.020000|size=846|pos=251168|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=457200|pts_time=5.080000|dts=457200|dts_time=5.080000|duration=1800|duration_time=0.020000|size=846|pos=251168|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2803c379 -packet|codec_type=audio|stream_index=0|pts=459000|pts_time=5.100000|dts=459000|dts_time=5.100000|duration=1800|duration_time=0.020000|size=775|pos=252108|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=459000|pts_time=5.100000|dts=459000|dts_time=5.100000|duration=1800|duration_time=0.020000|size=775|pos=252108|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2d95b53b -packet|codec_type=audio|stream_index=0|pts=460800|pts_time=5.120000|dts=460800|dts_time=5.120000|duration=1800|duration_time=0.020000|size=901|pos=253048|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=460800|pts_time=5.120000|dts=460800|dts_time=5.120000|duration=1800|duration_time=0.020000|size=901|pos=253048|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2a40955c -packet|codec_type=audio|stream_index=0|pts=462600|pts_time=5.140000|dts=462600|dts_time=5.140000|duration=1800|duration_time=0.020000|size=958|pos=254176|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=462600|pts_time=5.140000|dts=462600|dts_time=5.140000|duration=1800|duration_time=0.020000|size=958|pos=254176|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b46687d4 -packet|codec_type=audio|stream_index=0|pts=464400|pts_time=5.160000|dts=464400|dts_time=5.160000|duration=1800|duration_time=0.020000|size=770|pos=255304|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=464400|pts_time=5.160000|dts=464400|dts_time=5.160000|duration=1800|duration_time=0.020000|size=770|pos=255304|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c4ec89eb -packet|codec_type=audio|stream_index=0|pts=466200|pts_time=5.180000|dts=466200|dts_time=5.180000|duration=1800|duration_time=0.020000|size=773|pos=256244|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=466200|pts_time=5.180000|dts=466200|dts_time=5.180000|duration=1800|duration_time=0.020000|size=773|pos=256244|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d53fcf9c -packet|codec_type=audio|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=1800|duration_time=0.020000|size=768|pos=257560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=1800|duration_time=0.020000|size=768|pos=257560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:eb9bfc19 -packet|codec_type=audio|stream_index=0|pts=469800|pts_time=5.220000|dts=469800|dts_time=5.220000|duration=1800|duration_time=0.020000|size=776|pos=258500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=469800|pts_time=5.220000|dts=469800|dts_time=5.220000|duration=1800|duration_time=0.020000|size=776|pos=258500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:71e70489 -packet|codec_type=audio|stream_index=0|pts=471600|pts_time=5.240000|dts=471600|dts_time=5.240000|duration=1800|duration_time=0.020000|size=771|pos=259440|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=471600|pts_time=5.240000|dts=471600|dts_time=5.240000|duration=1800|duration_time=0.020000|size=771|pos=259440|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:60a96aca -packet|codec_type=audio|stream_index=0|pts=473400|pts_time=5.260000|dts=473400|dts_time=5.260000|duration=1800|duration_time=0.020000|size=772|pos=260380|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=473400|pts_time=5.260000|dts=473400|dts_time=5.260000|duration=1800|duration_time=0.020000|size=772|pos=260380|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ceca878e -packet|codec_type=audio|stream_index=0|pts=475200|pts_time=5.280000|dts=475200|dts_time=5.280000|duration=1800|duration_time=0.020000|size=958|pos=261320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=475200|pts_time=5.280000|dts=475200|dts_time=5.280000|duration=1800|duration_time=0.020000|size=958|pos=261320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ab40ffe7 -packet|codec_type=audio|stream_index=0|pts=477000|pts_time=5.300000|dts=477000|dts_time=5.300000|duration=1800|duration_time=0.020000|size=771|pos=262448|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=477000|pts_time=5.300000|dts=477000|dts_time=5.300000|duration=1800|duration_time=0.020000|size=771|pos=262448|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0f8c3162 -packet|codec_type=audio|stream_index=0|pts=478800|pts_time=5.320000|dts=478800|dts_time=5.320000|duration=1800|duration_time=0.020000|size=770|pos=263388|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=478800|pts_time=5.320000|dts=478800|dts_time=5.320000|duration=1800|duration_time=0.020000|size=770|pos=263388|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:af837825 -packet|codec_type=audio|stream_index=0|pts=480600|pts_time=5.340000|dts=480600|dts_time=5.340000|duration=1800|duration_time=0.020000|size=959|pos=264328|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=480600|pts_time=5.340000|dts=480600|dts_time=5.340000|duration=1800|duration_time=0.020000|size=959|pos=264328|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:93a1bea9 -packet|codec_type=audio|stream_index=0|pts=482400|pts_time=5.360000|dts=482400|dts_time=5.360000|duration=1800|duration_time=0.020000|size=769|pos=265456|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=482400|pts_time=5.360000|dts=482400|dts_time=5.360000|duration=1800|duration_time=0.020000|size=769|pos=265456|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e7289ab0 -packet|codec_type=audio|stream_index=0|pts=484200|pts_time=5.380000|dts=484200|dts_time=5.380000|duration=1800|duration_time=0.020000|size=840|pos=266396|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=484200|pts_time=5.380000|dts=484200|dts_time=5.380000|duration=1800|duration_time=0.020000|size=840|pos=266396|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4b39626e -packet|codec_type=audio|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=1800|duration_time=0.020000|size=769|pos=267712|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=1800|duration_time=0.020000|size=769|pos=267712|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f4bc91d6 -packet|codec_type=audio|stream_index=0|pts=487800|pts_time=5.420000|dts=487800|dts_time=5.420000|duration=1800|duration_time=0.020000|size=767|pos=268652|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=487800|pts_time=5.420000|dts=487800|dts_time=5.420000|duration=1800|duration_time=0.020000|size=767|pos=268652|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:68dd482f -packet|codec_type=audio|stream_index=0|pts=489600|pts_time=5.440000|dts=489600|dts_time=5.440000|duration=1800|duration_time=0.020000|size=951|pos=269592|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=489600|pts_time=5.440000|dts=489600|dts_time=5.440000|duration=1800|duration_time=0.020000|size=951|pos=269592|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:61ab6014 -packet|codec_type=audio|stream_index=0|pts=491400|pts_time=5.460000|dts=491400|dts_time=5.460000|duration=1800|duration_time=0.020000|size=769|pos=270720|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=491400|pts_time=5.460000|dts=491400|dts_time=5.460000|duration=1800|duration_time=0.020000|size=769|pos=270720|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:232f6af8 -packet|codec_type=audio|stream_index=0|pts=493200|pts_time=5.480000|dts=493200|dts_time=5.480000|duration=1800|duration_time=0.020000|size=958|pos=271660|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=493200|pts_time=5.480000|dts=493200|dts_time=5.480000|duration=1800|duration_time=0.020000|size=958|pos=271660|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9a4372e9 -packet|codec_type=audio|stream_index=0|pts=495000|pts_time=5.500000|dts=495000|dts_time=5.500000|duration=1800|duration_time=0.020000|size=773|pos=272788|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=495000|pts_time=5.500000|dts=495000|dts_time=5.500000|duration=1800|duration_time=0.020000|size=773|pos=272788|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f7044435 -packet|codec_type=audio|stream_index=0|pts=496800|pts_time=5.520000|dts=496800|dts_time=5.520000|duration=1800|duration_time=0.020000|size=771|pos=273728|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=496800|pts_time=5.520000|dts=496800|dts_time=5.520000|duration=1800|duration_time=0.020000|size=771|pos=273728|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2d36f75f -packet|codec_type=audio|stream_index=0|pts=498600|pts_time=5.540000|dts=498600|dts_time=5.540000|duration=1800|duration_time=0.020000|size=768|pos=274668|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=498600|pts_time=5.540000|dts=498600|dts_time=5.540000|duration=1800|duration_time=0.020000|size=768|pos=274668|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:11858457 -packet|codec_type=audio|stream_index=0|pts=500400|pts_time=5.560000|dts=500400|dts_time=5.560000|duration=1800|duration_time=0.020000|size=765|pos=275608|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=500400|pts_time=5.560000|dts=500400|dts_time=5.560000|duration=1800|duration_time=0.020000|size=765|pos=275608|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:104cc3b1 -packet|codec_type=audio|stream_index=0|pts=502200|pts_time=5.580000|dts=502200|dts_time=5.580000|duration=1800|duration_time=0.020000|size=774|pos=276548|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=502200|pts_time=5.580000|dts=502200|dts_time=5.580000|duration=1800|duration_time=0.020000|size=774|pos=276548|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8ed3cf9c -packet|codec_type=audio|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=1800|duration_time=0.020000|size=837|pos=277864|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=1800|duration_time=0.020000|size=837|pos=277864|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:16b50427 -packet|codec_type=audio|stream_index=0|pts=505800|pts_time=5.620000|dts=505800|dts_time=5.620000|duration=1800|duration_time=0.020000|size=773|pos=278804|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=505800|pts_time=5.620000|dts=505800|dts_time=5.620000|duration=1800|duration_time=0.020000|size=773|pos=278804|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c5c042c3 -packet|codec_type=audio|stream_index=0|pts=507600|pts_time=5.640000|dts=507600|dts_time=5.640000|duration=1800|duration_time=0.020000|size=773|pos=279744|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=507600|pts_time=5.640000|dts=507600|dts_time=5.640000|duration=1800|duration_time=0.020000|size=773|pos=279744|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:722e401f -packet|codec_type=audio|stream_index=0|pts=509400|pts_time=5.660000|dts=509400|dts_time=5.660000|duration=1800|duration_time=0.020000|size=770|pos=280684|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=509400|pts_time=5.660000|dts=509400|dts_time=5.660000|duration=1800|duration_time=0.020000|size=770|pos=280684|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:831f3604 -packet|codec_type=audio|stream_index=0|pts=511200|pts_time=5.680000|dts=511200|dts_time=5.680000|duration=1800|duration_time=0.020000|size=770|pos=281624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=511200|pts_time=5.680000|dts=511200|dts_time=5.680000|duration=1800|duration_time=0.020000|size=770|pos=281624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7718e73e -packet|codec_type=audio|stream_index=0|pts=513000|pts_time=5.700000|dts=513000|dts_time=5.700000|duration=1800|duration_time=0.020000|size=774|pos=282564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=513000|pts_time=5.700000|dts=513000|dts_time=5.700000|duration=1800|duration_time=0.020000|size=774|pos=282564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:170731a0 -packet|codec_type=audio|stream_index=0|pts=514800|pts_time=5.720000|dts=514800|dts_time=5.720000|duration=1800|duration_time=0.020000|size=767|pos=283504|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=514800|pts_time=5.720000|dts=514800|dts_time=5.720000|duration=1800|duration_time=0.020000|size=767|pos=283504|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d73c42a8 -packet|codec_type=audio|stream_index=0|pts=516600|pts_time=5.740000|dts=516600|dts_time=5.740000|duration=1800|duration_time=0.020000|size=774|pos=284444|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=516600|pts_time=5.740000|dts=516600|dts_time=5.740000|duration=1800|duration_time=0.020000|size=774|pos=284444|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:854f9a2e -packet|codec_type=audio|stream_index=0|pts=518400|pts_time=5.760000|dts=518400|dts_time=5.760000|duration=1800|duration_time=0.020000|size=833|pos=285384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=518400|pts_time=5.760000|dts=518400|dts_time=5.760000|duration=1800|duration_time=0.020000|size=833|pos=285384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7d64106d -packet|codec_type=audio|stream_index=0|pts=520200|pts_time=5.780000|dts=520200|dts_time=5.780000|duration=1800|duration_time=0.020000|size=774|pos=286324|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=520200|pts_time=5.780000|dts=520200|dts_time=5.780000|duration=1800|duration_time=0.020000|size=774|pos=286324|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:02e139fa -packet|codec_type=audio|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=1800|duration_time=0.020000|size=768|pos=287640|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=1800|duration_time=0.020000|size=768|pos=287640|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8b5d5f3b -packet|codec_type=audio|stream_index=0|pts=523800|pts_time=5.820000|dts=523800|dts_time=5.820000|duration=1800|duration_time=0.020000|size=773|pos=288580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=523800|pts_time=5.820000|dts=523800|dts_time=5.820000|duration=1800|duration_time=0.020000|size=773|pos=288580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fa25f507 -packet|codec_type=audio|stream_index=0|pts=525600|pts_time=5.840000|dts=525600|dts_time=5.840000|duration=1800|duration_time=0.020000|size=768|pos=289520|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=525600|pts_time=5.840000|dts=525600|dts_time=5.840000|duration=1800|duration_time=0.020000|size=768|pos=289520|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ccbf6593 -packet|codec_type=audio|stream_index=0|pts=527400|pts_time=5.860000|dts=527400|dts_time=5.860000|duration=1800|duration_time=0.020000|size=769|pos=290460|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=527400|pts_time=5.860000|dts=527400|dts_time=5.860000|duration=1800|duration_time=0.020000|size=769|pos=290460|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cea23a52 -packet|codec_type=audio|stream_index=0|pts=529200|pts_time=5.880000|dts=529200|dts_time=5.880000|duration=1800|duration_time=0.020000|size=767|pos=291400|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=529200|pts_time=5.880000|dts=529200|dts_time=5.880000|duration=1800|duration_time=0.020000|size=767|pos=291400|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3ff8eced -packet|codec_type=audio|stream_index=0|pts=531000|pts_time=5.900000|dts=531000|dts_time=5.900000|duration=1800|duration_time=0.020000|size=773|pos=292340|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=531000|pts_time=5.900000|dts=531000|dts_time=5.900000|duration=1800|duration_time=0.020000|size=773|pos=292340|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a5d92bfd -packet|codec_type=audio|stream_index=0|pts=532800|pts_time=5.920000|dts=532800|dts_time=5.920000|duration=1800|duration_time=0.020000|size=774|pos=293280|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=532800|pts_time=5.920000|dts=532800|dts_time=5.920000|duration=1800|duration_time=0.020000|size=774|pos=293280|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:582c9c2e -packet|codec_type=audio|stream_index=0|pts=534600|pts_time=5.940000|dts=534600|dts_time=5.940000|duration=1800|duration_time=0.020000|size=769|pos=294220|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=534600|pts_time=5.940000|dts=534600|dts_time=5.940000|duration=1800|duration_time=0.020000|size=769|pos=294220|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc23f8d9 -packet|codec_type=audio|stream_index=0|pts=536400|pts_time=5.960000|dts=536400|dts_time=5.960000|duration=1800|duration_time=0.020000|size=833|pos=295160|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=536400|pts_time=5.960000|dts=536400|dts_time=5.960000|duration=1800|duration_time=0.020000|size=833|pos=295160|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5b9a2c15 -packet|codec_type=audio|stream_index=0|pts=538200|pts_time=5.980000|dts=538200|dts_time=5.980000|duration=1800|duration_time=0.020000|size=768|pos=296100|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=538200|pts_time=5.980000|dts=538200|dts_time=5.980000|duration=1800|duration_time=0.020000|size=768|pos=296100|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8c48e7c5 -packet|codec_type=audio|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=1800|duration_time=0.020000|size=772|pos=297416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=1800|duration_time=0.020000|size=772|pos=297416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c431b153 -packet|codec_type=audio|stream_index=0|pts=541800|pts_time=6.020000|dts=541800|dts_time=6.020000|duration=1800|duration_time=0.020000|size=839|pos=298356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=541800|pts_time=6.020000|dts=541800|dts_time=6.020000|duration=1800|duration_time=0.020000|size=839|pos=298356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9cfe17d0 -packet|codec_type=audio|stream_index=0|pts=543600|pts_time=6.040000|dts=543600|dts_time=6.040000|duration=1800|duration_time=0.020000|size=769|pos=299296|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=543600|pts_time=6.040000|dts=543600|dts_time=6.040000|duration=1800|duration_time=0.020000|size=769|pos=299296|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:72510fbb -packet|codec_type=audio|stream_index=0|pts=545400|pts_time=6.060000|dts=545400|dts_time=6.060000|duration=1800|duration_time=0.020000|size=769|pos=300236|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=545400|pts_time=6.060000|dts=545400|dts_time=6.060000|duration=1800|duration_time=0.020000|size=769|pos=300236|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:81830ddd -packet|codec_type=audio|stream_index=0|pts=547200|pts_time=6.080000|dts=547200|dts_time=6.080000|duration=1800|duration_time=0.020000|size=771|pos=301176|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=547200|pts_time=6.080000|dts=547200|dts_time=6.080000|duration=1800|duration_time=0.020000|size=771|pos=301176|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:43102486 -packet|codec_type=audio|stream_index=0|pts=549000|pts_time=6.100000|dts=549000|dts_time=6.100000|duration=1800|duration_time=0.020000|size=770|pos=302116|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=549000|pts_time=6.100000|dts=549000|dts_time=6.100000|duration=1800|duration_time=0.020000|size=770|pos=302116|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:49018a2e -packet|codec_type=audio|stream_index=0|pts=550800|pts_time=6.120000|dts=550800|dts_time=6.120000|duration=1800|duration_time=0.020000|size=771|pos=303056|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=550800|pts_time=6.120000|dts=550800|dts_time=6.120000|duration=1800|duration_time=0.020000|size=771|pos=303056|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3a01967a -packet|codec_type=audio|stream_index=0|pts=552600|pts_time=6.140000|dts=552600|dts_time=6.140000|duration=1800|duration_time=0.020000|size=767|pos=303996|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=552600|pts_time=6.140000|dts=552600|dts_time=6.140000|duration=1800|duration_time=0.020000|size=767|pos=303996|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:028a7ab9 -packet|codec_type=audio|stream_index=0|pts=554400|pts_time=6.160000|dts=554400|dts_time=6.160000|duration=1800|duration_time=0.020000|size=899|pos=304936|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=554400|pts_time=6.160000|dts=554400|dts_time=6.160000|duration=1800|duration_time=0.020000|size=899|pos=304936|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:012e3f77 -packet|codec_type=audio|stream_index=0|pts=556200|pts_time=6.180000|dts=556200|dts_time=6.180000|duration=1800|duration_time=0.020000|size=953|pos=305876|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=556200|pts_time=6.180000|dts=556200|dts_time=6.180000|duration=1800|duration_time=0.020000|size=953|pos=305876|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:60935688 -packet|codec_type=audio|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=1800|duration_time=0.020000|size=770|pos=307380|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=1800|duration_time=0.020000|size=770|pos=307380|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1f54722f -packet|codec_type=audio|stream_index=0|pts=559800|pts_time=6.220000|dts=559800|dts_time=6.220000|duration=1800|duration_time=0.020000|size=770|pos=308320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=559800|pts_time=6.220000|dts=559800|dts_time=6.220000|duration=1800|duration_time=0.020000|size=770|pos=308320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7786349b -packet|codec_type=audio|stream_index=0|pts=561600|pts_time=6.240000|dts=561600|dts_time=6.240000|duration=1800|duration_time=0.020000|size=771|pos=309260|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=561600|pts_time=6.240000|dts=561600|dts_time=6.240000|duration=1800|duration_time=0.020000|size=771|pos=309260|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1be2464d -packet|codec_type=audio|stream_index=0|pts=563400|pts_time=6.260000|dts=563400|dts_time=6.260000|duration=1800|duration_time=0.020000|size=770|pos=310200|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=563400|pts_time=6.260000|dts=563400|dts_time=6.260000|duration=1800|duration_time=0.020000|size=770|pos=310200|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cf6b28b9 -packet|codec_type=audio|stream_index=0|pts=565200|pts_time=6.280000|dts=565200|dts_time=6.280000|duration=1800|duration_time=0.020000|size=769|pos=311140|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=565200|pts_time=6.280000|dts=565200|dts_time=6.280000|duration=1800|duration_time=0.020000|size=769|pos=311140|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:63fa4ab0 -packet|codec_type=audio|stream_index=0|pts=567000|pts_time=6.300000|dts=567000|dts_time=6.300000|duration=1800|duration_time=0.020000|size=896|pos=312080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=567000|pts_time=6.300000|dts=567000|dts_time=6.300000|duration=1800|duration_time=0.020000|size=896|pos=312080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:06a8e324 -packet|codec_type=audio|stream_index=0|pts=568800|pts_time=6.320000|dts=568800|dts_time=6.320000|duration=1800|duration_time=0.020000|size=957|pos=313020|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=568800|pts_time=6.320000|dts=568800|dts_time=6.320000|duration=1800|duration_time=0.020000|size=957|pos=313020|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c37f55e9 -packet|codec_type=audio|stream_index=0|pts=570600|pts_time=6.340000|dts=570600|dts_time=6.340000|duration=1800|duration_time=0.020000|size=773|pos=314148|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=570600|pts_time=6.340000|dts=570600|dts_time=6.340000|duration=1800|duration_time=0.020000|size=773|pos=314148|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:82f8ac84 -packet|codec_type=audio|stream_index=0|pts=572400|pts_time=6.360000|dts=572400|dts_time=6.360000|duration=1800|duration_time=0.020000|size=774|pos=315088|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=572400|pts_time=6.360000|dts=572400|dts_time=6.360000|duration=1800|duration_time=0.020000|size=774|pos=315088|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3ed82724 -packet|codec_type=audio|stream_index=0|pts=574200|pts_time=6.380000|dts=574200|dts_time=6.380000|duration=1800|duration_time=0.020000|size=956|pos=316028|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=574200|pts_time=6.380000|dts=574200|dts_time=6.380000|duration=1800|duration_time=0.020000|size=956|pos=316028|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ed21dfec -packet|codec_type=audio|stream_index=0|pts=576000|pts_time=6.400000|dts=576000|dts_time=6.400000|duration=1800|duration_time=0.020000|size=768|pos=317532|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=576000|pts_time=6.400000|dts=576000|dts_time=6.400000|duration=1800|duration_time=0.020000|size=768|pos=317532|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ef20c09c -packet|codec_type=audio|stream_index=0|pts=577800|pts_time=6.420000|dts=577800|dts_time=6.420000|duration=1800|duration_time=0.020000|size=770|pos=318472|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=577800|pts_time=6.420000|dts=577800|dts_time=6.420000|duration=1800|duration_time=0.020000|size=770|pos=318472|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5f72438e -packet|codec_type=audio|stream_index=0|pts=579600|pts_time=6.440000|dts=579600|dts_time=6.440000|duration=1800|duration_time=0.020000|size=771|pos=319412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=579600|pts_time=6.440000|dts=579600|dts_time=6.440000|duration=1800|duration_time=0.020000|size=771|pos=319412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:831f56d5 -packet|codec_type=audio|stream_index=0|pts=581400|pts_time=6.460000|dts=581400|dts_time=6.460000|duration=1800|duration_time=0.020000|size=955|pos=320352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=581400|pts_time=6.460000|dts=581400|dts_time=6.460000|duration=1800|duration_time=0.020000|size=955|pos=320352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a3fb153b -packet|codec_type=audio|stream_index=0|pts=583200|pts_time=6.480000|dts=583200|dts_time=6.480000|duration=1800|duration_time=0.020000|size=953|pos=321480|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=583200|pts_time=6.480000|dts=583200|dts_time=6.480000|duration=1800|duration_time=0.020000|size=953|pos=321480|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:109825ac -packet|codec_type=audio|stream_index=0|pts=585000|pts_time=6.500000|dts=585000|dts_time=6.500000|duration=1800|duration_time=0.020000|size=767|pos=322608|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=585000|pts_time=6.500000|dts=585000|dts_time=6.500000|duration=1800|duration_time=0.020000|size=767|pos=322608|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5cb97953 -packet|codec_type=audio|stream_index=0|pts=586800|pts_time=6.520000|dts=586800|dts_time=6.520000|duration=1800|duration_time=0.020000|size=768|pos=323548|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=586800|pts_time=6.520000|dts=586800|dts_time=6.520000|duration=1800|duration_time=0.020000|size=768|pos=323548|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9aa43658 -packet|codec_type=audio|stream_index=0|pts=588600|pts_time=6.540000|dts=588600|dts_time=6.540000|duration=1800|duration_time=0.020000|size=774|pos=324488|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=588600|pts_time=6.540000|dts=588600|dts_time=6.540000|duration=1800|duration_time=0.020000|size=774|pos=324488|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0ccad3c6 -packet|codec_type=audio|stream_index=0|pts=590400|pts_time=6.560000|dts=590400|dts_time=6.560000|duration=1800|duration_time=0.020000|size=835|pos=325428|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=590400|pts_time=6.560000|dts=590400|dts_time=6.560000|duration=1800|duration_time=0.020000|size=835|pos=325428|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee1e951f -packet|codec_type=audio|stream_index=0|pts=592200|pts_time=6.580000|dts=592200|dts_time=6.580000|duration=1800|duration_time=0.020000|size=768|pos=326368|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=592200|pts_time=6.580000|dts=592200|dts_time=6.580000|duration=1800|duration_time=0.020000|size=768|pos=326368|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7e964664 -packet|codec_type=audio|stream_index=0|pts=594000|pts_time=6.600000|dts=594000|dts_time=6.600000|duration=1800|duration_time=0.020000|size=769|pos=327684|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=594000|pts_time=6.600000|dts=594000|dts_time=6.600000|duration=1800|duration_time=0.020000|size=769|pos=327684|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:46489e72 -packet|codec_type=audio|stream_index=0|pts=595800|pts_time=6.620000|dts=595800|dts_time=6.620000|duration=1800|duration_time=0.020000|size=771|pos=328624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=595800|pts_time=6.620000|dts=595800|dts_time=6.620000|duration=1800|duration_time=0.020000|size=771|pos=328624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:528f881d -packet|codec_type=audio|stream_index=0|pts=597600|pts_time=6.640000|dts=597600|dts_time=6.640000|duration=1800|duration_time=0.020000|size=771|pos=329564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=597600|pts_time=6.640000|dts=597600|dts_time=6.640000|duration=1800|duration_time=0.020000|size=771|pos=329564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e776ddf8 -packet|codec_type=audio|stream_index=0|pts=599400|pts_time=6.660000|dts=599400|dts_time=6.660000|duration=1800|duration_time=0.020000|size=770|pos=330504|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=599400|pts_time=6.660000|dts=599400|dts_time=6.660000|duration=1800|duration_time=0.020000|size=770|pos=330504|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f4d9468d -packet|codec_type=audio|stream_index=0|pts=601200|pts_time=6.680000|dts=601200|dts_time=6.680000|duration=1800|duration_time=0.020000|size=768|pos=331444|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=601200|pts_time=6.680000|dts=601200|dts_time=6.680000|duration=1800|duration_time=0.020000|size=768|pos=331444|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0b5bc3e0 -packet|codec_type=audio|stream_index=0|pts=603000|pts_time=6.700000|dts=603000|dts_time=6.700000|duration=1800|duration_time=0.020000|size=951|pos=332384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=603000|pts_time=6.700000|dts=603000|dts_time=6.700000|duration=1800|duration_time=0.020000|size=951|pos=332384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4c6d023d -packet|codec_type=audio|stream_index=0|pts=604800|pts_time=6.720000|dts=604800|dts_time=6.720000|duration=1800|duration_time=0.020000|size=950|pos=333512|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=604800|pts_time=6.720000|dts=604800|dts_time=6.720000|duration=1800|duration_time=0.020000|size=950|pos=333512|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:29588833 -packet|codec_type=audio|stream_index=0|pts=606600|pts_time=6.740000|dts=606600|dts_time=6.740000|duration=1800|duration_time=0.020000|size=947|pos=334640|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=606600|pts_time=6.740000|dts=606600|dts_time=6.740000|duration=1800|duration_time=0.020000|size=947|pos=334640|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:12f446a5 -packet|codec_type=audio|stream_index=0|pts=608400|pts_time=6.760000|dts=608400|dts_time=6.760000|duration=1800|duration_time=0.020000|size=956|pos=335768|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=608400|pts_time=6.760000|dts=608400|dts_time=6.760000|duration=1800|duration_time=0.020000|size=956|pos=335768|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:39a765b6 -packet|codec_type=audio|stream_index=0|pts=610200|pts_time=6.780000|dts=610200|dts_time=6.780000|duration=1800|duration_time=0.020000|size=951|pos=336896|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=610200|pts_time=6.780000|dts=610200|dts_time=6.780000|duration=1800|duration_time=0.020000|size=951|pos=336896|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:79ab4162 -packet|codec_type=audio|stream_index=0|pts=612000|pts_time=6.800000|dts=612000|dts_time=6.800000|duration=1800|duration_time=0.020000|size=943|pos=338400|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=612000|pts_time=6.800000|dts=612000|dts_time=6.800000|duration=1800|duration_time=0.020000|size=943|pos=338400|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1c20d61c -packet|codec_type=audio|stream_index=0|pts=613800|pts_time=6.820000|dts=613800|dts_time=6.820000|duration=1800|duration_time=0.020000|size=766|pos=339528|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=613800|pts_time=6.820000|dts=613800|dts_time=6.820000|duration=1800|duration_time=0.020000|size=766|pos=339528|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0e5d1ee5 -packet|codec_type=audio|stream_index=0|pts=615600|pts_time=6.840000|dts=615600|dts_time=6.840000|duration=1800|duration_time=0.020000|size=890|pos=340468|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=615600|pts_time=6.840000|dts=615600|dts_time=6.840000|duration=1800|duration_time=0.020000|size=890|pos=340468|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:27c19b26 -packet|codec_type=audio|stream_index=0|pts=617400|pts_time=6.860000|dts=617400|dts_time=6.860000|duration=1800|duration_time=0.020000|size=952|pos=341408|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=617400|pts_time=6.860000|dts=617400|dts_time=6.860000|duration=1800|duration_time=0.020000|size=952|pos=341408|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8ba8ff4c -packet|codec_type=audio|stream_index=0|pts=619200|pts_time=6.880000|dts=619200|dts_time=6.880000|duration=1800|duration_time=0.020000|size=766|pos=342536|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=619200|pts_time=6.880000|dts=619200|dts_time=6.880000|duration=1800|duration_time=0.020000|size=766|pos=342536|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:61b51e53 -packet|codec_type=audio|stream_index=0|pts=621000|pts_time=6.900000|dts=621000|dts_time=6.900000|duration=1800|duration_time=0.020000|size=767|pos=343476|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=621000|pts_time=6.900000|dts=621000|dts_time=6.900000|duration=1800|duration_time=0.020000|size=767|pos=343476|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:223fd4b8 -packet|codec_type=audio|stream_index=0|pts=622800|pts_time=6.920000|dts=622800|dts_time=6.920000|duration=1800|duration_time=0.020000|size=760|pos=344416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=622800|pts_time=6.920000|dts=622800|dts_time=6.920000|duration=1800|duration_time=0.020000|size=760|pos=344416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:221e6f8a -packet|codec_type=audio|stream_index=0|pts=624600|pts_time=6.940000|dts=624600|dts_time=6.940000|duration=1800|duration_time=0.020000|size=946|pos=345356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=624600|pts_time=6.940000|dts=624600|dts_time=6.940000|duration=1800|duration_time=0.020000|size=946|pos=345356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:623d901e -packet|codec_type=audio|stream_index=0|pts=626400|pts_time=6.960000|dts=626400|dts_time=6.960000|duration=1800|duration_time=0.020000|size=769|pos=346484|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=626400|pts_time=6.960000|dts=626400|dts_time=6.960000|duration=1800|duration_time=0.020000|size=769|pos=346484|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:584cd53d -packet|codec_type=audio|stream_index=0|pts=628200|pts_time=6.980000|dts=628200|dts_time=6.980000|duration=1800|duration_time=0.020000|size=760|pos=347424|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=628200|pts_time=6.980000|dts=628200|dts_time=6.980000|duration=1800|duration_time=0.020000|size=760|pos=347424|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:179b3137 -packet|codec_type=audio|stream_index=0|pts=630000|pts_time=7.000000|dts=630000|dts_time=7.000000|duration=1800|duration_time=0.020000|size=762|pos=348740|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=630000|pts_time=7.000000|dts=630000|dts_time=7.000000|duration=1800|duration_time=0.020000|size=762|pos=348740|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e0e617f2 -packet|codec_type=audio|stream_index=0|pts=631800|pts_time=7.020000|dts=631800|dts_time=7.020000|duration=1800|duration_time=0.020000|size=767|pos=349680|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=631800|pts_time=7.020000|dts=631800|dts_time=7.020000|duration=1800|duration_time=0.020000|size=767|pos=349680|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:560639a0 -packet|codec_type=audio|stream_index=0|pts=633600|pts_time=7.040000|dts=633600|dts_time=7.040000|duration=1800|duration_time=0.020000|size=767|pos=350620|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=633600|pts_time=7.040000|dts=633600|dts_time=7.040000|duration=1800|duration_time=0.020000|size=767|pos=350620|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a88ea02f -packet|codec_type=audio|stream_index=0|pts=635400|pts_time=7.060000|dts=635400|dts_time=7.060000|duration=1800|duration_time=0.020000|size=763|pos=351560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=635400|pts_time=7.060000|dts=635400|dts_time=7.060000|duration=1800|duration_time=0.020000|size=763|pos=351560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6a9f391f -packet|codec_type=audio|stream_index=0|pts=637200|pts_time=7.080000|dts=637200|dts_time=7.080000|duration=1800|duration_time=0.020000|size=760|pos=352500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=637200|pts_time=7.080000|dts=637200|dts_time=7.080000|duration=1800|duration_time=0.020000|size=760|pos=352500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:217730ab -packet|codec_type=audio|stream_index=0|pts=639000|pts_time=7.100000|dts=639000|dts_time=7.100000|duration=1800|duration_time=0.020000|size=763|pos=353440|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=639000|pts_time=7.100000|dts=639000|dts_time=7.100000|duration=1800|duration_time=0.020000|size=763|pos=353440|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ffa59273 -packet|codec_type=audio|stream_index=0|pts=640800|pts_time=7.120000|dts=640800|dts_time=7.120000|duration=1800|duration_time=0.020000|size=764|pos=354380|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=640800|pts_time=7.120000|dts=640800|dts_time=7.120000|duration=1800|duration_time=0.020000|size=764|pos=354380|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:05a70a45 -packet|codec_type=audio|stream_index=0|pts=642600|pts_time=7.140000|dts=642600|dts_time=7.140000|duration=1800|duration_time=0.020000|size=764|pos=355320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=642600|pts_time=7.140000|dts=642600|dts_time=7.140000|duration=1800|duration_time=0.020000|size=764|pos=355320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1e2e4d40 -packet|codec_type=audio|stream_index=0|pts=644400|pts_time=7.160000|dts=644400|dts_time=7.160000|duration=1800|duration_time=0.020000|size=763|pos=356260|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=644400|pts_time=7.160000|dts=644400|dts_time=7.160000|duration=1800|duration_time=0.020000|size=763|pos=356260|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:695b9d24 -packet|codec_type=audio|stream_index=0|pts=646200|pts_time=7.180000|dts=646200|dts_time=7.180000|duration=1800|duration_time=0.020000|size=763|pos=357200|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=646200|pts_time=7.180000|dts=646200|dts_time=7.180000|duration=1800|duration_time=0.020000|size=763|pos=357200|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:007b90ce -packet|codec_type=audio|stream_index=0|pts=648000|pts_time=7.200000|dts=648000|dts_time=7.200000|duration=1800|duration_time=0.020000|size=764|pos=358516|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=648000|pts_time=7.200000|dts=648000|dts_time=7.200000|duration=1800|duration_time=0.020000|size=764|pos=358516|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:188da6de -packet|codec_type=audio|stream_index=0|pts=649800|pts_time=7.220000|dts=649800|dts_time=7.220000|duration=1800|duration_time=0.020000|size=766|pos=359456|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=649800|pts_time=7.220000|dts=649800|dts_time=7.220000|duration=1800|duration_time=0.020000|size=766|pos=359456|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1046d54c -packet|codec_type=audio|stream_index=0|pts=651600|pts_time=7.240000|dts=651600|dts_time=7.240000|duration=1800|duration_time=0.020000|size=767|pos=360396|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=651600|pts_time=7.240000|dts=651600|dts_time=7.240000|duration=1800|duration_time=0.020000|size=767|pos=360396|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aa450d3d -packet|codec_type=audio|stream_index=0|pts=653400|pts_time=7.260000|dts=653400|dts_time=7.260000|duration=1800|duration_time=0.020000|size=765|pos=361336|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=653400|pts_time=7.260000|dts=653400|dts_time=7.260000|duration=1800|duration_time=0.020000|size=765|pos=361336|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:80bb936b -packet|codec_type=audio|stream_index=0|pts=655200|pts_time=7.280000|dts=655200|dts_time=7.280000|duration=1800|duration_time=0.020000|size=767|pos=362276|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=655200|pts_time=7.280000|dts=655200|dts_time=7.280000|duration=1800|duration_time=0.020000|size=767|pos=362276|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:47bc2556 -packet|codec_type=audio|stream_index=0|pts=657000|pts_time=7.300000|dts=657000|dts_time=7.300000|duration=1800|duration_time=0.020000|size=763|pos=363216|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=657000|pts_time=7.300000|dts=657000|dts_time=7.300000|duration=1800|duration_time=0.020000|size=763|pos=363216|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:97d4c99c -packet|codec_type=audio|stream_index=0|pts=658800|pts_time=7.320000|dts=658800|dts_time=7.320000|duration=1800|duration_time=0.020000|size=767|pos=364156|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=658800|pts_time=7.320000|dts=658800|dts_time=7.320000|duration=1800|duration_time=0.020000|size=767|pos=364156|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:37252d43 -packet|codec_type=audio|stream_index=0|pts=660600|pts_time=7.340000|dts=660600|dts_time=7.340000|duration=1800|duration_time=0.020000|size=768|pos=365096|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=660600|pts_time=7.340000|dts=660600|dts_time=7.340000|duration=1800|duration_time=0.020000|size=768|pos=365096|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:76918244 -packet|codec_type=audio|stream_index=0|pts=662400|pts_time=7.360000|dts=662400|dts_time=7.360000|duration=1800|duration_time=0.020000|size=764|pos=366036|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=662400|pts_time=7.360000|dts=662400|dts_time=7.360000|duration=1800|duration_time=0.020000|size=764|pos=366036|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5ba0d5d3 -packet|codec_type=audio|stream_index=0|pts=664200|pts_time=7.380000|dts=664200|dts_time=7.380000|duration=1800|duration_time=0.020000|size=765|pos=366976|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=664200|pts_time=7.380000|dts=664200|dts_time=7.380000|duration=1800|duration_time=0.020000|size=765|pos=366976|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5b2b81f0 -packet|codec_type=audio|stream_index=0|pts=666000|pts_time=7.400000|dts=666000|dts_time=7.400000|duration=1800|duration_time=0.020000|size=764|pos=368292|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=666000|pts_time=7.400000|dts=666000|dts_time=7.400000|duration=1800|duration_time=0.020000|size=764|pos=368292|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:161f0b38 -packet|codec_type=audio|stream_index=0|pts=667800|pts_time=7.420000|dts=667800|dts_time=7.420000|duration=1800|duration_time=0.020000|size=769|pos=369232|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=667800|pts_time=7.420000|dts=667800|dts_time=7.420000|duration=1800|duration_time=0.020000|size=769|pos=369232|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:78b4530b -packet|codec_type=audio|stream_index=0|pts=669600|pts_time=7.440000|dts=669600|dts_time=7.440000|duration=1800|duration_time=0.020000|size=766|pos=370172|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=669600|pts_time=7.440000|dts=669600|dts_time=7.440000|duration=1800|duration_time=0.020000|size=766|pos=370172|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c0844a4f -packet|codec_type=audio|stream_index=0|pts=671400|pts_time=7.460000|dts=671400|dts_time=7.460000|duration=1800|duration_time=0.020000|size=766|pos=371112|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=671400|pts_time=7.460000|dts=671400|dts_time=7.460000|duration=1800|duration_time=0.020000|size=766|pos=371112|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:09ef7940 -packet|codec_type=audio|stream_index=0|pts=673200|pts_time=7.480000|dts=673200|dts_time=7.480000|duration=1800|duration_time=0.020000|size=829|pos=372052|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=673200|pts_time=7.480000|dts=673200|dts_time=7.480000|duration=1800|duration_time=0.020000|size=829|pos=372052|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:053ff4c6 -packet|codec_type=audio|stream_index=0|pts=675000|pts_time=7.500000|dts=675000|dts_time=7.500000|duration=1800|duration_time=0.020000|size=765|pos=372992|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=675000|pts_time=7.500000|dts=675000|dts_time=7.500000|duration=1800|duration_time=0.020000|size=765|pos=372992|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dffb6a19 -packet|codec_type=audio|stream_index=0|pts=676800|pts_time=7.520000|dts=676800|dts_time=7.520000|duration=1800|duration_time=0.020000|size=766|pos=373932|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=676800|pts_time=7.520000|dts=676800|dts_time=7.520000|duration=1800|duration_time=0.020000|size=766|pos=373932|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:95240406 -packet|codec_type=audio|stream_index=0|pts=678600|pts_time=7.540000|dts=678600|dts_time=7.540000|duration=1800|duration_time=0.020000|size=766|pos=374872|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=678600|pts_time=7.540000|dts=678600|dts_time=7.540000|duration=1800|duration_time=0.020000|size=766|pos=374872|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e2e8f563 -packet|codec_type=audio|stream_index=0|pts=680400|pts_time=7.560000|dts=680400|dts_time=7.560000|duration=1800|duration_time=0.020000|size=898|pos=375812|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=680400|pts_time=7.560000|dts=680400|dts_time=7.560000|duration=1800|duration_time=0.020000|size=898|pos=375812|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c1c53334 -packet|codec_type=audio|stream_index=0|pts=682200|pts_time=7.580000|dts=682200|dts_time=7.580000|duration=1800|duration_time=0.020000|size=767|pos=376940|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=682200|pts_time=7.580000|dts=682200|dts_time=7.580000|duration=1800|duration_time=0.020000|size=767|pos=376940|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f122e957 -packet|codec_type=audio|stream_index=0|pts=684000|pts_time=7.600000|dts=684000|dts_time=7.600000|duration=1800|duration_time=0.020000|size=896|pos=378256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=684000|pts_time=7.600000|dts=684000|dts_time=7.600000|duration=1800|duration_time=0.020000|size=896|pos=378256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cd022652 -packet|codec_type=audio|stream_index=0|pts=685800|pts_time=7.620000|dts=685800|dts_time=7.620000|duration=1800|duration_time=0.020000|size=764|pos=379196|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=685800|pts_time=7.620000|dts=685800|dts_time=7.620000|duration=1800|duration_time=0.020000|size=764|pos=379196|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:909c400c -packet|codec_type=audio|stream_index=0|pts=687600|pts_time=7.640000|dts=687600|dts_time=7.640000|duration=1800|duration_time=0.020000|size=762|pos=380136|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=687600|pts_time=7.640000|dts=687600|dts_time=7.640000|duration=1800|duration_time=0.020000|size=762|pos=380136|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7340fb8d -packet|codec_type=audio|stream_index=0|pts=689400|pts_time=7.660000|dts=689400|dts_time=7.660000|duration=1800|duration_time=0.020000|size=762|pos=381076|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=689400|pts_time=7.660000|dts=689400|dts_time=7.660000|duration=1800|duration_time=0.020000|size=762|pos=381076|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:46b59223 -packet|codec_type=audio|stream_index=0|pts=691200|pts_time=7.680000|dts=691200|dts_time=7.680000|duration=1800|duration_time=0.020000|size=763|pos=382016|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=691200|pts_time=7.680000|dts=691200|dts_time=7.680000|duration=1800|duration_time=0.020000|size=763|pos=382016|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2f1ebb7e -packet|codec_type=audio|stream_index=0|pts=693000|pts_time=7.700000|dts=693000|dts_time=7.700000|duration=1800|duration_time=0.020000|size=947|pos=382956|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=693000|pts_time=7.700000|dts=693000|dts_time=7.700000|duration=1800|duration_time=0.020000|size=947|pos=382956|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b56bee4b -packet|codec_type=audio|stream_index=0|pts=694800|pts_time=7.720000|dts=694800|dts_time=7.720000|duration=1800|duration_time=0.020000|size=767|pos=384084|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=694800|pts_time=7.720000|dts=694800|dts_time=7.720000|duration=1800|duration_time=0.020000|size=767|pos=384084|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57c778a9 -packet|codec_type=audio|stream_index=0|pts=696600|pts_time=7.740000|dts=696600|dts_time=7.740000|duration=1800|duration_time=0.020000|size=957|pos=385024|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=696600|pts_time=7.740000|dts=696600|dts_time=7.740000|duration=1800|duration_time=0.020000|size=957|pos=385024|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:599b6964 -packet|codec_type=audio|stream_index=0|pts=698400|pts_time=7.760000|dts=698400|dts_time=7.760000|duration=1800|duration_time=0.020000|size=955|pos=386152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=698400|pts_time=7.760000|dts=698400|dts_time=7.760000|duration=1800|duration_time=0.020000|size=955|pos=386152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2351bfa3 -packet|codec_type=audio|stream_index=0|pts=700200|pts_time=7.780000|dts=700200|dts_time=7.780000|duration=1800|duration_time=0.020000|size=767|pos=387280|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=700200|pts_time=7.780000|dts=700200|dts_time=7.780000|duration=1800|duration_time=0.020000|size=767|pos=387280|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f31f5d14 -packet|codec_type=audio|stream_index=0|pts=702000|pts_time=7.800000|dts=702000|dts_time=7.800000|duration=1800|duration_time=0.020000|size=767|pos=388596|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=702000|pts_time=7.800000|dts=702000|dts_time=7.800000|duration=1800|duration_time=0.020000|size=767|pos=388596|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c0f7f4b5 -packet|codec_type=audio|stream_index=0|pts=703800|pts_time=7.820000|dts=703800|dts_time=7.820000|duration=1800|duration_time=0.020000|size=764|pos=389536|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=703800|pts_time=7.820000|dts=703800|dts_time=7.820000|duration=1800|duration_time=0.020000|size=764|pos=389536|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f321de8a -packet|codec_type=audio|stream_index=0|pts=705600|pts_time=7.840000|dts=705600|dts_time=7.840000|duration=1800|duration_time=0.020000|size=763|pos=390476|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=705600|pts_time=7.840000|dts=705600|dts_time=7.840000|duration=1800|duration_time=0.020000|size=763|pos=390476|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:64e7e790 -packet|codec_type=audio|stream_index=0|pts=707400|pts_time=7.860000|dts=707400|dts_time=7.860000|duration=1800|duration_time=0.020000|size=769|pos=391416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=707400|pts_time=7.860000|dts=707400|dts_time=7.860000|duration=1800|duration_time=0.020000|size=769|pos=391416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d9bef93e -packet|codec_type=audio|stream_index=0|pts=709200|pts_time=7.880000|dts=709200|dts_time=7.880000|duration=1800|duration_time=0.020000|size=766|pos=392356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=709200|pts_time=7.880000|dts=709200|dts_time=7.880000|duration=1800|duration_time=0.020000|size=766|pos=392356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b08e677b -packet|codec_type=audio|stream_index=0|pts=711000|pts_time=7.900000|dts=711000|dts_time=7.900000|duration=1800|duration_time=0.020000|size=762|pos=393296|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=711000|pts_time=7.900000|dts=711000|dts_time=7.900000|duration=1800|duration_time=0.020000|size=762|pos=393296|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc2d57f3 -packet|codec_type=audio|stream_index=0|pts=712800|pts_time=7.920000|dts=712800|dts_time=7.920000|duration=1800|duration_time=0.020000|size=766|pos=394236|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=712800|pts_time=7.920000|dts=712800|dts_time=7.920000|duration=1800|duration_time=0.020000|size=766|pos=394236|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:920b310d -packet|codec_type=audio|stream_index=0|pts=714600|pts_time=7.940000|dts=714600|dts_time=7.940000|duration=1800|duration_time=0.020000|size=768|pos=395176|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=714600|pts_time=7.940000|dts=714600|dts_time=7.940000|duration=1800|duration_time=0.020000|size=768|pos=395176|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7547a71e -packet|codec_type=audio|stream_index=0|pts=716400|pts_time=7.960000|dts=716400|dts_time=7.960000|duration=1800|duration_time=0.020000|size=765|pos=396116|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=716400|pts_time=7.960000|dts=716400|dts_time=7.960000|duration=1800|duration_time=0.020000|size=765|pos=396116|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6d0f72a9 -packet|codec_type=audio|stream_index=0|pts=718200|pts_time=7.980000|dts=718200|dts_time=7.980000|duration=1800|duration_time=0.020000|size=953|pos=397056|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=718200|pts_time=7.980000|dts=718200|dts_time=7.980000|duration=1800|duration_time=0.020000|size=953|pos=397056|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6daae92b -packet|codec_type=audio|stream_index=0|pts=720000|pts_time=8.000000|dts=720000|dts_time=8.000000|duration=1800|duration_time=0.020000|size=769|pos=398560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=720000|pts_time=8.000000|dts=720000|dts_time=8.000000|duration=1800|duration_time=0.020000|size=769|pos=398560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8bd8704e -packet|codec_type=audio|stream_index=0|pts=721800|pts_time=8.020000|dts=721800|dts_time=8.020000|duration=1800|duration_time=0.020000|size=955|pos=399500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=721800|pts_time=8.020000|dts=721800|dts_time=8.020000|duration=1800|duration_time=0.020000|size=955|pos=399500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:111f49de -packet|codec_type=audio|stream_index=0|pts=723600|pts_time=8.040000|dts=723600|dts_time=8.040000|duration=1800|duration_time=0.020000|size=952|pos=400628|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=723600|pts_time=8.040000|dts=723600|dts_time=8.040000|duration=1800|duration_time=0.020000|size=952|pos=400628|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6e266d5 -packet|codec_type=audio|stream_index=0|pts=725400|pts_time=8.060000|dts=725400|dts_time=8.060000|duration=1800|duration_time=0.020000|size=951|pos=401756|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=725400|pts_time=8.060000|dts=725400|dts_time=8.060000|duration=1800|duration_time=0.020000|size=951|pos=401756|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b0f5283f -packet|codec_type=audio|stream_index=0|pts=727200|pts_time=8.080000|dts=727200|dts_time=8.080000|duration=1800|duration_time=0.020000|size=954|pos=402884|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=727200|pts_time=8.080000|dts=727200|dts_time=8.080000|duration=1800|duration_time=0.020000|size=954|pos=402884|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f70d4475 -packet|codec_type=audio|stream_index=0|pts=729000|pts_time=8.100000|dts=729000|dts_time=8.100000|duration=1800|duration_time=0.020000|size=948|pos=404012|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=729000|pts_time=8.100000|dts=729000|dts_time=8.100000|duration=1800|duration_time=0.020000|size=948|pos=404012|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:371078df -packet|codec_type=audio|stream_index=0|pts=730800|pts_time=8.120000|dts=730800|dts_time=8.120000|duration=1800|duration_time=0.020000|size=761|pos=405140|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=730800|pts_time=8.120000|dts=730800|dts_time=8.120000|duration=1800|duration_time=0.020000|size=761|pos=405140|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c2aa814b -packet|codec_type=audio|stream_index=0|pts=732600|pts_time=8.140000|dts=732600|dts_time=8.140000|duration=1800|duration_time=0.020000|size=763|pos=406080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=732600|pts_time=8.140000|dts=732600|dts_time=8.140000|duration=1800|duration_time=0.020000|size=763|pos=406080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:188194bc -packet|codec_type=audio|stream_index=0|pts=734400|pts_time=8.160000|dts=734400|dts_time=8.160000|duration=1800|duration_time=0.020000|size=760|pos=407020|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=734400|pts_time=8.160000|dts=734400|dts_time=8.160000|duration=1800|duration_time=0.020000|size=760|pos=407020|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:982ba78c -packet|codec_type=audio|stream_index=0|pts=736200|pts_time=8.180000|dts=736200|dts_time=8.180000|duration=1800|duration_time=0.020000|size=764|pos=407960|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=736200|pts_time=8.180000|dts=736200|dts_time=8.180000|duration=1800|duration_time=0.020000|size=764|pos=407960|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bf244c73 -packet|codec_type=audio|stream_index=0|pts=738000|pts_time=8.200000|dts=738000|dts_time=8.200000|duration=1800|duration_time=0.020000|size=764|pos=409276|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=738000|pts_time=8.200000|dts=738000|dts_time=8.200000|duration=1800|duration_time=0.020000|size=764|pos=409276|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8bdf82ed -packet|codec_type=audio|stream_index=0|pts=739800|pts_time=8.220000|dts=739800|dts_time=8.220000|duration=1800|duration_time=0.020000|size=946|pos=410216|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=739800|pts_time=8.220000|dts=739800|dts_time=8.220000|duration=1800|duration_time=0.020000|size=946|pos=410216|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:acb2d4f3 -packet|codec_type=audio|stream_index=0|pts=741600|pts_time=8.240000|dts=741600|dts_time=8.240000|duration=1800|duration_time=0.020000|size=758|pos=411344|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=741600|pts_time=8.240000|dts=741600|dts_time=8.240000|duration=1800|duration_time=0.020000|size=758|pos=411344|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1cefab3c -packet|codec_type=audio|stream_index=0|pts=743400|pts_time=8.260000|dts=743400|dts_time=8.260000|duration=1800|duration_time=0.020000|size=950|pos=412284|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=743400|pts_time=8.260000|dts=743400|dts_time=8.260000|duration=1800|duration_time=0.020000|size=950|pos=412284|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0bd02594 -packet|codec_type=audio|stream_index=0|pts=745200|pts_time=8.280000|dts=745200|dts_time=8.280000|duration=1800|duration_time=0.020000|size=769|pos=413412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=745200|pts_time=8.280000|dts=745200|dts_time=8.280000|duration=1800|duration_time=0.020000|size=769|pos=413412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc6fff1d -packet|codec_type=audio|stream_index=0|pts=747000|pts_time=8.300000|dts=747000|dts_time=8.300000|duration=1800|duration_time=0.020000|size=764|pos=414352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=747000|pts_time=8.300000|dts=747000|dts_time=8.300000|duration=1800|duration_time=0.020000|size=764|pos=414352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cb2fc3d9 -packet|codec_type=audio|stream_index=0|pts=748800|pts_time=8.320000|dts=748800|dts_time=8.320000|duration=1800|duration_time=0.020000|size=757|pos=415292|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=748800|pts_time=8.320000|dts=748800|dts_time=8.320000|duration=1800|duration_time=0.020000|size=757|pos=415292|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:860da403 -packet|codec_type=audio|stream_index=0|pts=750600|pts_time=8.340000|dts=750600|dts_time=8.340000|duration=1800|duration_time=0.020000|size=761|pos=416232|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=750600|pts_time=8.340000|dts=750600|dts_time=8.340000|duration=1800|duration_time=0.020000|size=761|pos=416232|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:14aca2c6 -packet|codec_type=audio|stream_index=0|pts=752400|pts_time=8.360000|dts=752400|dts_time=8.360000|duration=1800|duration_time=0.020000|size=761|pos=417172|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=752400|pts_time=8.360000|dts=752400|dts_time=8.360000|duration=1800|duration_time=0.020000|size=761|pos=417172|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c5d24ee7 -packet|codec_type=audio|stream_index=0|pts=754200|pts_time=8.380000|dts=754200|dts_time=8.380000|duration=1800|duration_time=0.020000|size=759|pos=418112|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=754200|pts_time=8.380000|dts=754200|dts_time=8.380000|duration=1800|duration_time=0.020000|size=759|pos=418112|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:91680f09 -packet|codec_type=audio|stream_index=0|pts=756000|pts_time=8.400000|dts=756000|dts_time=8.400000|duration=1800|duration_time=0.020000|size=758|pos=419428|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=756000|pts_time=8.400000|dts=756000|dts_time=8.400000|duration=1800|duration_time=0.020000|size=758|pos=419428|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6b2948d -packet|codec_type=audio|stream_index=0|pts=757800|pts_time=8.420000|dts=757800|dts_time=8.420000|duration=1800|duration_time=0.020000|size=767|pos=420368|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=757800|pts_time=8.420000|dts=757800|dts_time=8.420000|duration=1800|duration_time=0.020000|size=767|pos=420368|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:20ff251c -packet|codec_type=audio|stream_index=0|pts=759600|pts_time=8.440000|dts=759600|dts_time=8.440000|duration=1800|duration_time=0.020000|size=761|pos=421308|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=759600|pts_time=8.440000|dts=759600|dts_time=8.440000|duration=1800|duration_time=0.020000|size=761|pos=421308|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d9fa6569 -packet|codec_type=audio|stream_index=0|pts=761400|pts_time=8.460000|dts=761400|dts_time=8.460000|duration=1800|duration_time=0.020000|size=828|pos=422248|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=761400|pts_time=8.460000|dts=761400|dts_time=8.460000|duration=1800|duration_time=0.020000|size=828|pos=422248|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:871a83c7 -packet|codec_type=audio|stream_index=0|pts=763200|pts_time=8.480000|dts=763200|dts_time=8.480000|duration=1800|duration_time=0.020000|size=759|pos=423188|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=763200|pts_time=8.480000|dts=763200|dts_time=8.480000|duration=1800|duration_time=0.020000|size=759|pos=423188|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ad2423ee -packet|codec_type=audio|stream_index=0|pts=765000|pts_time=8.500000|dts=765000|dts_time=8.500000|duration=1800|duration_time=0.020000|size=761|pos=424128|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=765000|pts_time=8.500000|dts=765000|dts_time=8.500000|duration=1800|duration_time=0.020000|size=761|pos=424128|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4e9b7b6e -packet|codec_type=audio|stream_index=0|pts=766800|pts_time=8.520000|dts=766800|dts_time=8.520000|duration=1800|duration_time=0.020000|size=762|pos=425068|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=766800|pts_time=8.520000|dts=766800|dts_time=8.520000|duration=1800|duration_time=0.020000|size=762|pos=425068|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4aa3582f -packet|codec_type=audio|stream_index=0|pts=768600|pts_time=8.540000|dts=768600|dts_time=8.540000|duration=1800|duration_time=0.020000|size=761|pos=426008|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=768600|pts_time=8.540000|dts=768600|dts_time=8.540000|duration=1800|duration_time=0.020000|size=761|pos=426008|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:15952f9f -packet|codec_type=audio|stream_index=0|pts=770400|pts_time=8.560000|dts=770400|dts_time=8.560000|duration=1800|duration_time=0.020000|size=757|pos=426948|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=770400|pts_time=8.560000|dts=770400|dts_time=8.560000|duration=1800|duration_time=0.020000|size=757|pos=426948|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:55db10c7 -packet|codec_type=audio|stream_index=0|pts=772200|pts_time=8.580000|dts=772200|dts_time=8.580000|duration=1800|duration_time=0.020000|size=759|pos=427888|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=772200|pts_time=8.580000|dts=772200|dts_time=8.580000|duration=1800|duration_time=0.020000|size=759|pos=427888|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1cfff77c -packet|codec_type=audio|stream_index=0|pts=774000|pts_time=8.600000|dts=774000|dts_time=8.600000|duration=1800|duration_time=0.020000|size=759|pos=429204|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=774000|pts_time=8.600000|dts=774000|dts_time=8.600000|duration=1800|duration_time=0.020000|size=759|pos=429204|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:93bf7a2e -packet|codec_type=audio|stream_index=0|pts=775800|pts_time=8.620000|dts=775800|dts_time=8.620000|duration=1800|duration_time=0.020000|size=761|pos=430144|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=775800|pts_time=8.620000|dts=775800|dts_time=8.620000|duration=1800|duration_time=0.020000|size=761|pos=430144|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:75577b1c -packet|codec_type=audio|stream_index=0|pts=777600|pts_time=8.640000|dts=777600|dts_time=8.640000|duration=1800|duration_time=0.020000|size=756|pos=431084|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=777600|pts_time=8.640000|dts=777600|dts_time=8.640000|duration=1800|duration_time=0.020000|size=756|pos=431084|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fe81112c -packet|codec_type=audio|stream_index=0|pts=779400|pts_time=8.660000|dts=779400|dts_time=8.660000|duration=1800|duration_time=0.020000|size=765|pos=432024|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=779400|pts_time=8.660000|dts=779400|dts_time=8.660000|duration=1800|duration_time=0.020000|size=765|pos=432024|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0ddc28c1 -packet|codec_type=audio|stream_index=0|pts=781200|pts_time=8.680000|dts=781200|dts_time=8.680000|duration=1800|duration_time=0.020000|size=759|pos=432964|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=781200|pts_time=8.680000|dts=781200|dts_time=8.680000|duration=1800|duration_time=0.020000|size=759|pos=432964|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9dda185 -packet|codec_type=audio|stream_index=0|pts=783000|pts_time=8.700000|dts=783000|dts_time=8.700000|duration=1800|duration_time=0.020000|size=759|pos=433904|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=783000|pts_time=8.700000|dts=783000|dts_time=8.700000|duration=1800|duration_time=0.020000|size=759|pos=433904|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e10197bd -packet|codec_type=audio|stream_index=0|pts=784800|pts_time=8.720000|dts=784800|dts_time=8.720000|duration=1800|duration_time=0.020000|size=761|pos=434844|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=784800|pts_time=8.720000|dts=784800|dts_time=8.720000|duration=1800|duration_time=0.020000|size=761|pos=434844|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f1683c68 -packet|codec_type=audio|stream_index=0|pts=786600|pts_time=8.740000|dts=786600|dts_time=8.740000|duration=1800|duration_time=0.020000|size=762|pos=435784|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=786600|pts_time=8.740000|dts=786600|dts_time=8.740000|duration=1800|duration_time=0.020000|size=762|pos=435784|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f6eee942 -packet|codec_type=audio|stream_index=0|pts=788400|pts_time=8.760000|dts=788400|dts_time=8.760000|duration=1800|duration_time=0.020000|size=771|pos=436724|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=788400|pts_time=8.760000|dts=788400|dts_time=8.760000|duration=1800|duration_time=0.020000|size=771|pos=436724|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6ab1ef22 -packet|codec_type=audio|stream_index=0|pts=790200|pts_time=8.780000|dts=790200|dts_time=8.780000|duration=1800|duration_time=0.020000|size=758|pos=437664|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=790200|pts_time=8.780000|dts=790200|dts_time=8.780000|duration=1800|duration_time=0.020000|size=758|pos=437664|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6920a9e6 -packet|codec_type=audio|stream_index=0|pts=792000|pts_time=8.800000|dts=792000|dts_time=8.800000|duration=1800|duration_time=0.020000|size=759|pos=438980|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=792000|pts_time=8.800000|dts=792000|dts_time=8.800000|duration=1800|duration_time=0.020000|size=759|pos=438980|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b3ba03c7 -packet|codec_type=audio|stream_index=0|pts=793800|pts_time=8.820000|dts=793800|dts_time=8.820000|duration=1800|duration_time=0.020000|size=760|pos=439920|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=793800|pts_time=8.820000|dts=793800|dts_time=8.820000|duration=1800|duration_time=0.020000|size=760|pos=439920|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59f04151 -packet|codec_type=audio|stream_index=0|pts=795600|pts_time=8.840000|dts=795600|dts_time=8.840000|duration=1800|duration_time=0.020000|size=762|pos=440860|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=795600|pts_time=8.840000|dts=795600|dts_time=8.840000|duration=1800|duration_time=0.020000|size=762|pos=440860|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9300525 -packet|codec_type=audio|stream_index=0|pts=797400|pts_time=8.860000|dts=797400|dts_time=8.860000|duration=1800|duration_time=0.020000|size=760|pos=441800|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=797400|pts_time=8.860000|dts=797400|dts_time=8.860000|duration=1800|duration_time=0.020000|size=760|pos=441800|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:06b28e48 -packet|codec_type=audio|stream_index=0|pts=799200|pts_time=8.880000|dts=799200|dts_time=8.880000|duration=1800|duration_time=0.020000|size=760|pos=442740|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=799200|pts_time=8.880000|dts=799200|dts_time=8.880000|duration=1800|duration_time=0.020000|size=760|pos=442740|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:99640c9a -packet|codec_type=audio|stream_index=0|pts=801000|pts_time=8.900000|dts=801000|dts_time=8.900000|duration=1800|duration_time=0.020000|size=757|pos=443680|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=801000|pts_time=8.900000|dts=801000|dts_time=8.900000|duration=1800|duration_time=0.020000|size=757|pos=443680|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:264f20e3 -packet|codec_type=audio|stream_index=0|pts=802800|pts_time=8.920000|dts=802800|dts_time=8.920000|duration=1800|duration_time=0.020000|size=762|pos=444620|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=802800|pts_time=8.920000|dts=802800|dts_time=8.920000|duration=1800|duration_time=0.020000|size=762|pos=444620|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:87799aaa -packet|codec_type=audio|stream_index=0|pts=804600|pts_time=8.940000|dts=804600|dts_time=8.940000|duration=1800|duration_time=0.020000|size=763|pos=445560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=804600|pts_time=8.940000|dts=804600|dts_time=8.940000|duration=1800|duration_time=0.020000|size=763|pos=445560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b2487f0b -packet|codec_type=audio|stream_index=0|pts=806400|pts_time=8.960000|dts=806400|dts_time=8.960000|duration=1800|duration_time=0.020000|size=835|pos=446500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=806400|pts_time=8.960000|dts=806400|dts_time=8.960000|duration=1800|duration_time=0.020000|size=835|pos=446500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5ff97478 -packet|codec_type=audio|stream_index=0|pts=808200|pts_time=8.980000|dts=808200|dts_time=8.980000|duration=1800|duration_time=0.020000|size=758|pos=447440|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=808200|pts_time=8.980000|dts=808200|dts_time=8.980000|duration=1800|duration_time=0.020000|size=758|pos=447440|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee962000 -packet|codec_type=audio|stream_index=0|pts=810000|pts_time=9.000000|dts=810000|dts_time=9.000000|duration=1800|duration_time=0.020000|size=761|pos=448756|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=810000|pts_time=9.000000|dts=810000|dts_time=9.000000|duration=1800|duration_time=0.020000|size=761|pos=448756|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:65a93707 -packet|codec_type=audio|stream_index=0|pts=811800|pts_time=9.020000|dts=811800|dts_time=9.020000|duration=1800|duration_time=0.020000|size=888|pos=449696|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=811800|pts_time=9.020000|dts=811800|dts_time=9.020000|duration=1800|duration_time=0.020000|size=888|pos=449696|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f365394f -packet|codec_type=audio|stream_index=0|pts=813600|pts_time=9.040000|dts=813600|dts_time=9.040000|duration=1800|duration_time=0.020000|size=758|pos=450636|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=813600|pts_time=9.040000|dts=813600|dts_time=9.040000|duration=1800|duration_time=0.020000|size=758|pos=450636|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc4aa3e5 -packet|codec_type=audio|stream_index=0|pts=815400|pts_time=9.060000|dts=815400|dts_time=9.060000|duration=1800|duration_time=0.020000|size=765|pos=451576|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=815400|pts_time=9.060000|dts=815400|dts_time=9.060000|duration=1800|duration_time=0.020000|size=765|pos=451576|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a1fd5bac -packet|codec_type=audio|stream_index=0|pts=817200|pts_time=9.080000|dts=817200|dts_time=9.080000|duration=1800|duration_time=0.020000|size=761|pos=452516|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=817200|pts_time=9.080000|dts=817200|dts_time=9.080000|duration=1800|duration_time=0.020000|size=761|pos=452516|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1590afda -packet|codec_type=audio|stream_index=0|pts=819000|pts_time=9.100000|dts=819000|dts_time=9.100000|duration=1800|duration_time=0.020000|size=764|pos=453456|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=819000|pts_time=9.100000|dts=819000|dts_time=9.100000|duration=1800|duration_time=0.020000|size=764|pos=453456|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3e34e250 -packet|codec_type=audio|stream_index=0|pts=820800|pts_time=9.120000|dts=820800|dts_time=9.120000|duration=1800|duration_time=0.020000|size=762|pos=454396|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=820800|pts_time=9.120000|dts=820800|dts_time=9.120000|duration=1800|duration_time=0.020000|size=762|pos=454396|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:927657b5 -packet|codec_type=audio|stream_index=0|pts=822600|pts_time=9.140000|dts=822600|dts_time=9.140000|duration=1800|duration_time=0.020000|size=767|pos=455336|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=822600|pts_time=9.140000|dts=822600|dts_time=9.140000|duration=1800|duration_time=0.020000|size=767|pos=455336|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5261b6ab -packet|codec_type=audio|stream_index=0|pts=824400|pts_time=9.160000|dts=824400|dts_time=9.160000|duration=1800|duration_time=0.020000|size=759|pos=456276|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=824400|pts_time=9.160000|dts=824400|dts_time=9.160000|duration=1800|duration_time=0.020000|size=759|pos=456276|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:645fd792 -packet|codec_type=audio|stream_index=0|pts=826200|pts_time=9.180000|dts=826200|dts_time=9.180000|duration=1800|duration_time=0.020000|size=761|pos=457216|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=826200|pts_time=9.180000|dts=826200|dts_time=9.180000|duration=1800|duration_time=0.020000|size=761|pos=457216|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:240a9cd8 -packet|codec_type=audio|stream_index=0|pts=828000|pts_time=9.200000|dts=828000|dts_time=9.200000|duration=1800|duration_time=0.020000|size=762|pos=458532|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=828000|pts_time=9.200000|dts=828000|dts_time=9.200000|duration=1800|duration_time=0.020000|size=762|pos=458532|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:409c4ee6 -packet|codec_type=audio|stream_index=0|pts=829800|pts_time=9.220000|dts=829800|dts_time=9.220000|duration=1800|duration_time=0.020000|size=763|pos=459472|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=829800|pts_time=9.220000|dts=829800|dts_time=9.220000|duration=1800|duration_time=0.020000|size=763|pos=459472|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a1e4f6c8 -packet|codec_type=audio|stream_index=0|pts=831600|pts_time=9.240000|dts=831600|dts_time=9.240000|duration=1800|duration_time=0.020000|size=760|pos=460412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=831600|pts_time=9.240000|dts=831600|dts_time=9.240000|duration=1800|duration_time=0.020000|size=760|pos=460412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e405b6d8 -packet|codec_type=audio|stream_index=0|pts=833400|pts_time=9.260000|dts=833400|dts_time=9.260000|duration=1800|duration_time=0.020000|size=832|pos=461352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=833400|pts_time=9.260000|dts=833400|dts_time=9.260000|duration=1800|duration_time=0.020000|size=832|pos=461352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:28926870 -packet|codec_type=audio|stream_index=0|pts=835200|pts_time=9.280000|dts=835200|dts_time=9.280000|duration=1800|duration_time=0.020000|size=761|pos=462292|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=835200|pts_time=9.280000|dts=835200|dts_time=9.280000|duration=1800|duration_time=0.020000|size=761|pos=462292|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:991eafa7 -packet|codec_type=audio|stream_index=0|pts=837000|pts_time=9.300000|dts=837000|dts_time=9.300000|duration=1800|duration_time=0.020000|size=887|pos=463232|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=837000|pts_time=9.300000|dts=837000|dts_time=9.300000|duration=1800|duration_time=0.020000|size=887|pos=463232|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2f2180e4 -packet|codec_type=audio|stream_index=0|pts=838800|pts_time=9.320000|dts=838800|dts_time=9.320000|duration=1800|duration_time=0.020000|size=765|pos=464172|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=838800|pts_time=9.320000|dts=838800|dts_time=9.320000|duration=1800|duration_time=0.020000|size=765|pos=464172|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c3b931ab -packet|codec_type=audio|stream_index=0|pts=840600|pts_time=9.340000|dts=840600|dts_time=9.340000|duration=1800|duration_time=0.020000|size=763|pos=465112|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=840600|pts_time=9.340000|dts=840600|dts_time=9.340000|duration=1800|duration_time=0.020000|size=763|pos=465112|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:09c95d1c -packet|codec_type=audio|stream_index=0|pts=842400|pts_time=9.360000|dts=842400|dts_time=9.360000|duration=1800|duration_time=0.020000|size=763|pos=466052|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=842400|pts_time=9.360000|dts=842400|dts_time=9.360000|duration=1800|duration_time=0.020000|size=763|pos=466052|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5a90f4d9 -packet|codec_type=audio|stream_index=0|pts=844200|pts_time=9.380000|dts=844200|dts_time=9.380000|duration=1800|duration_time=0.020000|size=952|pos=466992|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=844200|pts_time=9.380000|dts=844200|dts_time=9.380000|duration=1800|duration_time=0.020000|size=952|pos=466992|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2e1338bd -packet|codec_type=audio|stream_index=0|pts=846000|pts_time=9.400000|dts=846000|dts_time=9.400000|duration=1800|duration_time=0.020000|size=953|pos=468496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=846000|pts_time=9.400000|dts=846000|dts_time=9.400000|duration=1800|duration_time=0.020000|size=953|pos=468496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:db87e979 -packet|codec_type=audio|stream_index=0|pts=847800|pts_time=9.420000|dts=847800|dts_time=9.420000|duration=1800|duration_time=0.020000|size=945|pos=469624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=847800|pts_time=9.420000|dts=847800|dts_time=9.420000|duration=1800|duration_time=0.020000|size=945|pos=469624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d55815d6 -packet|codec_type=audio|stream_index=0|pts=849600|pts_time=9.440000|dts=849600|dts_time=9.440000|duration=1800|duration_time=0.020000|size=948|pos=470752|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=849600|pts_time=9.440000|dts=849600|dts_time=9.440000|duration=1800|duration_time=0.020000|size=948|pos=470752|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e31e5728 -packet|codec_type=audio|stream_index=0|pts=851400|pts_time=9.460000|dts=851400|dts_time=9.460000|duration=1800|duration_time=0.020000|size=951|pos=471880|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=851400|pts_time=9.460000|dts=851400|dts_time=9.460000|duration=1800|duration_time=0.020000|size=951|pos=471880|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:49e86c3d -packet|codec_type=audio|stream_index=0|pts=853200|pts_time=9.480000|dts=853200|dts_time=9.480000|duration=1800|duration_time=0.020000|size=826|pos=473008|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=853200|pts_time=9.480000|dts=853200|dts_time=9.480000|duration=1800|duration_time=0.020000|size=826|pos=473008|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:13cefb19 -packet|codec_type=audio|stream_index=0|pts=855000|pts_time=9.500000|dts=855000|dts_time=9.500000|duration=1800|duration_time=0.020000|size=763|pos=473948|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=855000|pts_time=9.500000|dts=855000|dts_time=9.500000|duration=1800|duration_time=0.020000|size=763|pos=473948|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8d9b7d72 -packet|codec_type=audio|stream_index=0|pts=856800|pts_time=9.520000|dts=856800|dts_time=9.520000|duration=1800|duration_time=0.020000|size=763|pos=474888|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=856800|pts_time=9.520000|dts=856800|dts_time=9.520000|duration=1800|duration_time=0.020000|size=763|pos=474888|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d55b35fb -packet|codec_type=audio|stream_index=0|pts=858600|pts_time=9.540000|dts=858600|dts_time=9.540000|duration=1800|duration_time=0.020000|size=766|pos=475828|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=858600|pts_time=9.540000|dts=858600|dts_time=9.540000|duration=1800|duration_time=0.020000|size=766|pos=475828|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3e10c46a -packet|codec_type=audio|stream_index=0|pts=860400|pts_time=9.560000|dts=860400|dts_time=9.560000|duration=1800|duration_time=0.020000|size=946|pos=476768|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=860400|pts_time=9.560000|dts=860400|dts_time=9.560000|duration=1800|duration_time=0.020000|size=946|pos=476768|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:924e67eb -packet|codec_type=audio|stream_index=0|pts=862200|pts_time=9.580000|dts=862200|dts_time=9.580000|duration=1800|duration_time=0.020000|size=762|pos=477896|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=862200|pts_time=9.580000|dts=862200|dts_time=9.580000|duration=1800|duration_time=0.020000|size=762|pos=477896|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:008c6ebb -packet|codec_type=audio|stream_index=0|pts=864000|pts_time=9.600000|dts=864000|dts_time=9.600000|duration=1800|duration_time=0.020000|size=765|pos=479212|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=864000|pts_time=9.600000|dts=864000|dts_time=9.600000|duration=1800|duration_time=0.020000|size=765|pos=479212|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:96d72d3f -packet|codec_type=audio|stream_index=0|pts=865800|pts_time=9.620000|dts=865800|dts_time=9.620000|duration=1800|duration_time=0.020000|size=763|pos=480152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=865800|pts_time=9.620000|dts=865800|dts_time=9.620000|duration=1800|duration_time=0.020000|size=763|pos=480152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6f40bb5a -packet|codec_type=audio|stream_index=0|pts=867600|pts_time=9.640000|dts=867600|dts_time=9.640000|duration=1800|duration_time=0.020000|size=761|pos=481092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=867600|pts_time=9.640000|dts=867600|dts_time=9.640000|duration=1800|duration_time=0.020000|size=761|pos=481092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f6ba1f01 -packet|codec_type=audio|stream_index=0|pts=869400|pts_time=9.660000|dts=869400|dts_time=9.660000|duration=1800|duration_time=0.020000|size=760|pos=482032|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=869400|pts_time=9.660000|dts=869400|dts_time=9.660000|duration=1800|duration_time=0.020000|size=760|pos=482032|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b610a31e -packet|codec_type=audio|stream_index=0|pts=871200|pts_time=9.680000|dts=871200|dts_time=9.680000|duration=1800|duration_time=0.020000|size=757|pos=482972|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=871200|pts_time=9.680000|dts=871200|dts_time=9.680000|duration=1800|duration_time=0.020000|size=757|pos=482972|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:64dde46b -packet|codec_type=audio|stream_index=0|pts=873000|pts_time=9.700000|dts=873000|dts_time=9.700000|duration=1800|duration_time=0.020000|size=757|pos=483912|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=873000|pts_time=9.700000|dts=873000|dts_time=9.700000|duration=1800|duration_time=0.020000|size=757|pos=483912|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8f794e6c -packet|codec_type=audio|stream_index=0|pts=874800|pts_time=9.720000|dts=874800|dts_time=9.720000|duration=1800|duration_time=0.020000|size=762|pos=484852|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=874800|pts_time=9.720000|dts=874800|dts_time=9.720000|duration=1800|duration_time=0.020000|size=762|pos=484852|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:65c6284c -packet|codec_type=audio|stream_index=0|pts=876600|pts_time=9.740000|dts=876600|dts_time=9.740000|duration=1800|duration_time=0.020000|size=760|pos=485792|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=876600|pts_time=9.740000|dts=876600|dts_time=9.740000|duration=1800|duration_time=0.020000|size=760|pos=485792|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7dead06c -packet|codec_type=audio|stream_index=0|pts=878400|pts_time=9.760000|dts=878400|dts_time=9.760000|duration=1800|duration_time=0.020000|size=763|pos=486732|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=878400|pts_time=9.760000|dts=878400|dts_time=9.760000|duration=1800|duration_time=0.020000|size=763|pos=486732|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b0e145b1 -packet|codec_type=audio|stream_index=0|pts=880200|pts_time=9.780000|dts=880200|dts_time=9.780000|duration=1800|duration_time=0.020000|size=764|pos=487672|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=880200|pts_time=9.780000|dts=880200|dts_time=9.780000|duration=1800|duration_time=0.020000|size=764|pos=487672|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3d2553f6 -packet|codec_type=audio|stream_index=0|pts=882000|pts_time=9.800000|dts=882000|dts_time=9.800000|duration=1800|duration_time=0.020000|size=946|pos=488988|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=882000|pts_time=9.800000|dts=882000|dts_time=9.800000|duration=1800|duration_time=0.020000|size=946|pos=488988|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e808f1d2 -packet|codec_type=audio|stream_index=0|pts=883800|pts_time=9.820000|dts=883800|dts_time=9.820000|duration=1800|duration_time=0.020000|size=946|pos=490116|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=883800|pts_time=9.820000|dts=883800|dts_time=9.820000|duration=1800|duration_time=0.020000|size=946|pos=490116|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6b408528 -packet|codec_type=audio|stream_index=0|pts=885600|pts_time=9.840000|dts=885600|dts_time=9.840000|duration=1800|duration_time=0.020000|size=949|pos=491244|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=885600|pts_time=9.840000|dts=885600|dts_time=9.840000|duration=1800|duration_time=0.020000|size=949|pos=491244|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e51d96e4 -packet|codec_type=audio|stream_index=0|pts=887400|pts_time=9.860000|dts=887400|dts_time=9.860000|duration=1800|duration_time=0.020000|size=946|pos=492372|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=887400|pts_time=9.860000|dts=887400|dts_time=9.860000|duration=1800|duration_time=0.020000|size=946|pos=492372|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c2df3280 -packet|codec_type=audio|stream_index=0|pts=889200|pts_time=9.880000|dts=889200|dts_time=9.880000|duration=1800|duration_time=0.020000|size=940|pos=493500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=889200|pts_time=9.880000|dts=889200|dts_time=9.880000|duration=1800|duration_time=0.020000|size=940|pos=493500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7bb5a137 -packet|codec_type=audio|stream_index=0|pts=891000|pts_time=9.900000|dts=891000|dts_time=9.900000|duration=1800|duration_time=0.020000|size=762|pos=494628|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=891000|pts_time=9.900000|dts=891000|dts_time=9.900000|duration=1800|duration_time=0.020000|size=762|pos=494628|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:12fcc651 -packet|codec_type=audio|stream_index=0|pts=892800|pts_time=9.920000|dts=892800|dts_time=9.920000|duration=1800|duration_time=0.020000|size=759|pos=495568|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=892800|pts_time=9.920000|dts=892800|dts_time=9.920000|duration=1800|duration_time=0.020000|size=759|pos=495568|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b402a4c8 -packet|codec_type=audio|stream_index=0|pts=894600|pts_time=9.940000|dts=894600|dts_time=9.940000|duration=1800|duration_time=0.020000|size=942|pos=496508|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=894600|pts_time=9.940000|dts=894600|dts_time=9.940000|duration=1800|duration_time=0.020000|size=942|pos=496508|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bfe52a16 -packet|codec_type=audio|stream_index=0|pts=896400|pts_time=9.960000|dts=896400|dts_time=9.960000|duration=1800|duration_time=0.020000|size=764|pos=497636|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=896400|pts_time=9.960000|dts=896400|dts_time=9.960000|duration=1800|duration_time=0.020000|size=764|pos=497636|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:09372283 -packet|codec_type=audio|stream_index=0|pts=898200|pts_time=9.980000|dts=898200|dts_time=9.980000|duration=1800|duration_time=0.020000|size=759|pos=498576|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=898200|pts_time=9.980000|dts=898200|dts_time=9.980000|duration=1800|duration_time=0.020000|size=759|pos=498576|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5a27db5c -packet|codec_type=audio|stream_index=0|pts=900000|pts_time=10.000000|dts=900000|dts_time=10.000000|duration=1800|duration_time=0.020000|size=760|pos=499892|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=900000|pts_time=10.000000|dts=900000|dts_time=10.000000|duration=1800|duration_time=0.020000|size=760|pos=499892|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0821b0cd -packet|codec_type=audio|stream_index=0|pts=901800|pts_time=10.020000|dts=901800|dts_time=10.020000|duration=1800|duration_time=0.020000|size=757|pos=500832|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=901800|pts_time=10.020000|dts=901800|dts_time=10.020000|duration=1800|duration_time=0.020000|size=757|pos=500832|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:91af6b99 -packet|codec_type=audio|stream_index=0|pts=903600|pts_time=10.040000|dts=903600|dts_time=10.040000|duration=1800|duration_time=0.020000|size=941|pos=501772|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=903600|pts_time=10.040000|dts=903600|dts_time=10.040000|duration=1800|duration_time=0.020000|size=941|pos=501772|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5296a88a -packet|codec_type=audio|stream_index=0|pts=905400|pts_time=10.060000|dts=905400|dts_time=10.060000|duration=1800|duration_time=0.020000|size=943|pos=502900|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=905400|pts_time=10.060000|dts=905400|dts_time=10.060000|duration=1800|duration_time=0.020000|size=943|pos=502900|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e75e69d4 -packet|codec_type=audio|stream_index=0|pts=907200|pts_time=10.080000|dts=907200|dts_time=10.080000|duration=1800|duration_time=0.020000|size=759|pos=504028|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=907200|pts_time=10.080000|dts=907200|dts_time=10.080000|duration=1800|duration_time=0.020000|size=759|pos=504028|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6a5b92cd -packet|codec_type=audio|stream_index=0|pts=909000|pts_time=10.100000|dts=909000|dts_time=10.100000|duration=1800|duration_time=0.020000|size=759|pos=504968|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=909000|pts_time=10.100000|dts=909000|dts_time=10.100000|duration=1800|duration_time=0.020000|size=759|pos=504968|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ec30c088 -packet|codec_type=audio|stream_index=0|pts=910800|pts_time=10.120000|dts=910800|dts_time=10.120000|duration=1800|duration_time=0.020000|size=762|pos=505908|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=910800|pts_time=10.120000|dts=910800|dts_time=10.120000|duration=1800|duration_time=0.020000|size=762|pos=505908|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2c73f2ff -packet|codec_type=audio|stream_index=0|pts=912600|pts_time=10.140000|dts=912600|dts_time=10.140000|duration=1800|duration_time=0.020000|size=831|pos=506848|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=912600|pts_time=10.140000|dts=912600|dts_time=10.140000|duration=1800|duration_time=0.020000|size=831|pos=506848|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7f7cb041 -packet|codec_type=audio|stream_index=0|pts=914400|pts_time=10.160000|dts=914400|dts_time=10.160000|duration=1800|duration_time=0.020000|size=756|pos=507788|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=914400|pts_time=10.160000|dts=914400|dts_time=10.160000|duration=1800|duration_time=0.020000|size=756|pos=507788|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:52ef1db9 -packet|codec_type=audio|stream_index=0|pts=916200|pts_time=10.180000|dts=916200|dts_time=10.180000|duration=1800|duration_time=0.020000|size=760|pos=508728|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=916200|pts_time=10.180000|dts=916200|dts_time=10.180000|duration=1800|duration_time=0.020000|size=760|pos=508728|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fdf0ce4a -packet|codec_type=audio|stream_index=0|pts=918000|pts_time=10.200000|dts=918000|dts_time=10.200000|duration=1800|duration_time=0.020000|size=761|pos=510044|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=918000|pts_time=10.200000|dts=918000|dts_time=10.200000|duration=1800|duration_time=0.020000|size=761|pos=510044|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:75113c11 -packet|codec_type=audio|stream_index=0|pts=919800|pts_time=10.220000|dts=919800|dts_time=10.220000|duration=1800|duration_time=0.020000|size=759|pos=510984|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=919800|pts_time=10.220000|dts=919800|dts_time=10.220000|duration=1800|duration_time=0.020000|size=759|pos=510984|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59fc266f stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=Opus|codec_tag=0x7375704f|sample_fmt=fltp|sample_rate=48000|channels=8|channel_layout=7.1|bits_per_sample=0|id=0x44|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=919800|duration=10.220000|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=512|extradata_size=29|extradata_hash=CRC32:6d6089a7|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=test-8-7.1.opus-small.ts|nb_streams=1|nb_programs=1|format_name=mpegts|start_time=0.000000|duration=10.220000|size=512000|bit_rate=400782|probe_score=50 diff --git a/tests/ref/fate/ts-small-demux b/tests/ref/fate/ts-small-demux index 1b0a21621b..3452fad4be 100644 --- a/tests/ref/fate/ts-small-demux +++ b/tests/ref/fate/ts-small-demux @@ -1,148 +1,148 @@ -packet|codec_type=video|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=6000|duration_time=0.066667|size=1290|pos=564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=6000|duration_time=0.066667|size=1290|pos=564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:9c4b744e -packet|codec_type=video|stream_index=0|pts=132000|pts_time=1.466667|dts=132000|dts_time=1.466667|duration=6000|duration_time=0.066667|size=21|pos=2068|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=132000|pts_time=1.466667|dts=132000|dts_time=1.466667|duration=6000|duration_time=0.066667|size=21|pos=2068|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f5490de8 -packet|codec_type=video|stream_index=0|pts=138000|pts_time=1.533333|dts=138000|dts_time=1.533333|duration=6000|duration_time=0.066667|size=15|pos=2256|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=138000|pts_time=1.533333|dts=138000|dts_time=1.533333|duration=6000|duration_time=0.066667|size=15|pos=2256|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=6000|duration_time=0.066667|size=15|pos=2444|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=6000|duration_time=0.066667|size=15|pos=2444|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=150000|pts_time=1.666667|dts=150000|dts_time=1.666667|duration=6000|duration_time=0.066667|size=15|pos=2632|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=150000|pts_time=1.666667|dts=150000|dts_time=1.666667|duration=6000|duration_time=0.066667|size=15|pos=2632|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=156000|pts_time=1.733333|dts=156000|dts_time=1.733333|duration=6000|duration_time=0.066667|size=15|pos=2820|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=156000|pts_time=1.733333|dts=156000|dts_time=1.733333|duration=6000|duration_time=0.066667|size=15|pos=2820|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=6000|duration_time=0.066667|size=15|pos=3008|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=6000|duration_time=0.066667|size=15|pos=3008|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=168000|pts_time=1.866667|dts=168000|dts_time=1.866667|duration=6000|duration_time=0.066667|size=15|pos=3196|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=168000|pts_time=1.866667|dts=168000|dts_time=1.866667|duration=6000|duration_time=0.066667|size=15|pos=3196|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=174000|pts_time=1.933333|dts=174000|dts_time=1.933333|duration=6000|duration_time=0.066667|size=15|pos=3384|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=174000|pts_time=1.933333|dts=174000|dts_time=1.933333|duration=6000|duration_time=0.066667|size=15|pos=3384|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=6000|duration_time=0.066667|size=15|pos=3572|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=6000|duration_time=0.066667|size=15|pos=3572|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=186000|pts_time=2.066667|dts=186000|dts_time=2.066667|duration=6000|duration_time=0.066667|size=15|pos=3760|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=186000|pts_time=2.066667|dts=186000|dts_time=2.066667|duration=6000|duration_time=0.066667|size=15|pos=3760|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=192000|pts_time=2.133333|dts=192000|dts_time=2.133333|duration=6000|duration_time=0.066667|size=15|pos=3948|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=192000|pts_time=2.133333|dts=192000|dts_time=2.133333|duration=6000|duration_time=0.066667|size=15|pos=3948|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=6000|duration_time=0.066667|size=15|pos=4136|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=6000|duration_time=0.066667|size=15|pos=4136|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=204000|pts_time=2.266667|dts=204000|dts_time=2.266667|duration=6000|duration_time=0.066667|size=15|pos=4324|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=204000|pts_time=2.266667|dts=204000|dts_time=2.266667|duration=6000|duration_time=0.066667|size=15|pos=4324|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=210000|pts_time=2.333333|dts=210000|dts_time=2.333333|duration=6000|duration_time=0.066667|size=15|pos=4512|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=210000|pts_time=2.333333|dts=210000|dts_time=2.333333|duration=6000|duration_time=0.066667|size=15|pos=4512|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=6000|duration_time=0.066667|size=15|pos=4700|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=6000|duration_time=0.066667|size=15|pos=4700|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=222000|pts_time=2.466667|dts=222000|dts_time=2.466667|duration=6000|duration_time=0.066667|size=15|pos=4888|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=222000|pts_time=2.466667|dts=222000|dts_time=2.466667|duration=6000|duration_time=0.066667|size=15|pos=4888|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=228000|pts_time=2.533333|dts=228000|dts_time=2.533333|duration=6000|duration_time=0.066667|size=15|pos=5076|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=228000|pts_time=2.533333|dts=228000|dts_time=2.533333|duration=6000|duration_time=0.066667|size=15|pos=5076|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=6000|duration_time=0.066667|size=15|pos=5264|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=6000|duration_time=0.066667|size=15|pos=5264|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=240000|pts_time=2.666667|dts=240000|dts_time=2.666667|duration=6000|duration_time=0.066667|size=15|pos=5452|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=240000|pts_time=2.666667|dts=240000|dts_time=2.666667|duration=6000|duration_time=0.066667|size=15|pos=5452|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=246000|pts_time=2.733333|dts=246000|dts_time=2.733333|duration=6000|duration_time=0.066667|size=15|pos=5640|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=246000|pts_time=2.733333|dts=246000|dts_time=2.733333|duration=6000|duration_time=0.066667|size=15|pos=5640|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=6000|duration_time=0.066667|size=15|pos=5828|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=6000|duration_time=0.066667|size=15|pos=5828|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=258000|pts_time=2.866667|dts=258000|dts_time=2.866667|duration=6000|duration_time=0.066667|size=15|pos=6016|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=258000|pts_time=2.866667|dts=258000|dts_time=2.866667|duration=6000|duration_time=0.066667|size=15|pos=6016|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=264000|pts_time=2.933333|dts=264000|dts_time=2.933333|duration=6000|duration_time=0.066667|size=15|pos=6204|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=264000|pts_time=2.933333|dts=264000|dts_time=2.933333|duration=6000|duration_time=0.066667|size=15|pos=6204|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=6000|duration_time=0.066667|size=15|pos=6392|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=6000|duration_time=0.066667|size=15|pos=6392|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=276000|pts_time=3.066667|dts=276000|dts_time=3.066667|duration=6000|duration_time=0.066667|size=15|pos=6580|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=276000|pts_time=3.066667|dts=276000|dts_time=3.066667|duration=6000|duration_time=0.066667|size=15|pos=6580|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=282000|pts_time=3.133333|dts=282000|dts_time=3.133333|duration=6000|duration_time=0.066667|size=15|pos=6768|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=282000|pts_time=3.133333|dts=282000|dts_time=3.133333|duration=6000|duration_time=0.066667|size=15|pos=6768|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=6000|duration_time=0.066667|size=15|pos=6956|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=6000|duration_time=0.066667|size=15|pos=6956|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=294000|pts_time=3.266667|dts=294000|dts_time=3.266667|duration=6000|duration_time=0.066667|size=15|pos=7144|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=294000|pts_time=3.266667|dts=294000|dts_time=3.266667|duration=6000|duration_time=0.066667|size=15|pos=7144|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=300000|pts_time=3.333333|dts=300000|dts_time=3.333333|duration=6000|duration_time=0.066667|size=15|pos=7332|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=300000|pts_time=3.333333|dts=300000|dts_time=3.333333|duration=6000|duration_time=0.066667|size=15|pos=7332|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=6000|duration_time=0.066667|size=15|pos=7520|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=6000|duration_time=0.066667|size=15|pos=7520|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=312000|pts_time=3.466667|dts=312000|dts_time=3.466667|duration=6000|duration_time=0.066667|size=15|pos=7708|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=312000|pts_time=3.466667|dts=312000|dts_time=3.466667|duration=6000|duration_time=0.066667|size=15|pos=7708|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=318000|pts_time=3.533333|dts=318000|dts_time=3.533333|duration=6000|duration_time=0.066667|size=15|pos=7896|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=318000|pts_time=3.533333|dts=318000|dts_time=3.533333|duration=6000|duration_time=0.066667|size=15|pos=7896|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=6000|duration_time=0.066667|size=15|pos=8460|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=6000|duration_time=0.066667|size=15|pos=8460|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=330000|pts_time=3.666667|dts=330000|dts_time=3.666667|duration=6000|duration_time=0.066667|size=15|pos=8648|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=330000|pts_time=3.666667|dts=330000|dts_time=3.666667|duration=6000|duration_time=0.066667|size=15|pos=8648|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=336000|pts_time=3.733333|dts=336000|dts_time=3.733333|duration=6000|duration_time=0.066667|size=15|pos=8836|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=336000|pts_time=3.733333|dts=336000|dts_time=3.733333|duration=6000|duration_time=0.066667|size=15|pos=8836|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=6000|duration_time=0.066667|size=15|pos=9024|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=6000|duration_time=0.066667|size=15|pos=9024|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=348000|pts_time=3.866667|dts=348000|dts_time=3.866667|duration=6000|duration_time=0.066667|size=15|pos=9212|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=348000|pts_time=3.866667|dts=348000|dts_time=3.866667|duration=6000|duration_time=0.066667|size=15|pos=9212|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=354000|pts_time=3.933333|dts=354000|dts_time=3.933333|duration=6000|duration_time=0.066667|size=15|pos=9400|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=354000|pts_time=3.933333|dts=354000|dts_time=3.933333|duration=6000|duration_time=0.066667|size=15|pos=9400|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=6000|duration_time=0.066667|size=15|pos=9588|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=6000|duration_time=0.066667|size=15|pos=9588|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=366000|pts_time=4.066667|dts=366000|dts_time=4.066667|duration=6000|duration_time=0.066667|size=15|pos=9776|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=366000|pts_time=4.066667|dts=366000|dts_time=4.066667|duration=6000|duration_time=0.066667|size=15|pos=9776|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=372000|pts_time=4.133333|dts=372000|dts_time=4.133333|duration=6000|duration_time=0.066667|size=15|pos=9964|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=372000|pts_time=4.133333|dts=372000|dts_time=4.133333|duration=6000|duration_time=0.066667|size=15|pos=9964|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=6000|duration_time=0.066667|size=15|pos=10152|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=6000|duration_time=0.066667|size=15|pos=10152|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=384000|pts_time=4.266667|dts=384000|dts_time=4.266667|duration=6000|duration_time=0.066667|size=15|pos=10340|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=384000|pts_time=4.266667|dts=384000|dts_time=4.266667|duration=6000|duration_time=0.066667|size=15|pos=10340|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=390000|pts_time=4.333333|dts=390000|dts_time=4.333333|duration=6000|duration_time=0.066667|size=15|pos=10528|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=390000|pts_time=4.333333|dts=390000|dts_time=4.333333|duration=6000|duration_time=0.066667|size=15|pos=10528|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=6000|duration_time=0.066667|size=15|pos=10716|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=6000|duration_time=0.066667|size=15|pos=10716|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=402000|pts_time=4.466667|dts=402000|dts_time=4.466667|duration=6000|duration_time=0.066667|size=15|pos=10904|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=402000|pts_time=4.466667|dts=402000|dts_time=4.466667|duration=6000|duration_time=0.066667|size=15|pos=10904|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=408000|pts_time=4.533333|dts=408000|dts_time=4.533333|duration=6000|duration_time=0.066667|size=15|pos=11092|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=408000|pts_time=4.533333|dts=408000|dts_time=4.533333|duration=6000|duration_time=0.066667|size=15|pos=11092|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=6000|duration_time=0.066667|size=15|pos=11280|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=6000|duration_time=0.066667|size=15|pos=11280|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=420000|pts_time=4.666667|dts=420000|dts_time=4.666667|duration=6000|duration_time=0.066667|size=15|pos=11468|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=420000|pts_time=4.666667|dts=420000|dts_time=4.666667|duration=6000|duration_time=0.066667|size=15|pos=11468|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=426000|pts_time=4.733333|dts=426000|dts_time=4.733333|duration=6000|duration_time=0.066667|size=15|pos=11656|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=426000|pts_time=4.733333|dts=426000|dts_time=4.733333|duration=6000|duration_time=0.066667|size=15|pos=11656|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=6000|duration_time=0.066667|size=15|pos=11844|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=6000|duration_time=0.066667|size=15|pos=11844|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=438000|pts_time=4.866667|dts=438000|dts_time=4.866667|duration=6000|duration_time=0.066667|size=15|pos=12032|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=438000|pts_time=4.866667|dts=438000|dts_time=4.866667|duration=6000|duration_time=0.066667|size=15|pos=12032|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=444000|pts_time=4.933333|dts=444000|dts_time=4.933333|duration=6000|duration_time=0.066667|size=15|pos=12220|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=444000|pts_time=4.933333|dts=444000|dts_time=4.933333|duration=6000|duration_time=0.066667|size=15|pos=12220|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=6000|duration_time=0.066667|size=15|pos=12408|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=6000|duration_time=0.066667|size=15|pos=12408|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=456000|pts_time=5.066667|dts=456000|dts_time=5.066667|duration=6000|duration_time=0.066667|size=15|pos=12596|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=456000|pts_time=5.066667|dts=456000|dts_time=5.066667|duration=6000|duration_time=0.066667|size=15|pos=12596|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=462000|pts_time=5.133333|dts=462000|dts_time=5.133333|duration=6000|duration_time=0.066667|size=15|pos=12784|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=462000|pts_time=5.133333|dts=462000|dts_time=5.133333|duration=6000|duration_time=0.066667|size=15|pos=12784|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=6000|duration_time=0.066667|size=15|pos=12972|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=6000|duration_time=0.066667|size=15|pos=12972|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=474000|pts_time=5.266667|dts=474000|dts_time=5.266667|duration=6000|duration_time=0.066667|size=15|pos=13160|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=474000|pts_time=5.266667|dts=474000|dts_time=5.266667|duration=6000|duration_time=0.066667|size=15|pos=13160|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=480000|pts_time=5.333333|dts=480000|dts_time=5.333333|duration=6000|duration_time=0.066667|size=15|pos=13348|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=480000|pts_time=5.333333|dts=480000|dts_time=5.333333|duration=6000|duration_time=0.066667|size=15|pos=13348|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=6000|duration_time=0.066667|size=15|pos=13536|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=6000|duration_time=0.066667|size=15|pos=13536|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=492000|pts_time=5.466667|dts=492000|dts_time=5.466667|duration=6000|duration_time=0.066667|size=15|pos=13724|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=492000|pts_time=5.466667|dts=492000|dts_time=5.466667|duration=6000|duration_time=0.066667|size=15|pos=13724|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=498000|pts_time=5.533333|dts=498000|dts_time=5.533333|duration=6000|duration_time=0.066667|size=15|pos=13912|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=498000|pts_time=5.533333|dts=498000|dts_time=5.533333|duration=6000|duration_time=0.066667|size=15|pos=13912|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=6000|duration_time=0.066667|size=15|pos=14100|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=6000|duration_time=0.066667|size=15|pos=14100|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=510000|pts_time=5.666667|dts=510000|dts_time=5.666667|duration=6000|duration_time=0.066667|size=15|pos=14288|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=510000|pts_time=5.666667|dts=510000|dts_time=5.666667|duration=6000|duration_time=0.066667|size=15|pos=14288|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=516000|pts_time=5.733333|dts=516000|dts_time=5.733333|duration=6000|duration_time=0.066667|size=15|pos=14476|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=516000|pts_time=5.733333|dts=516000|dts_time=5.733333|duration=6000|duration_time=0.066667|size=15|pos=14476|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=6000|duration_time=0.066667|size=15|pos=14664|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=6000|duration_time=0.066667|size=15|pos=14664|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=528000|pts_time=5.866667|dts=528000|dts_time=5.866667|duration=6000|duration_time=0.066667|size=15|pos=14852|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=528000|pts_time=5.866667|dts=528000|dts_time=5.866667|duration=6000|duration_time=0.066667|size=15|pos=14852|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=534000|pts_time=5.933333|dts=534000|dts_time=5.933333|duration=6000|duration_time=0.066667|size=15|pos=15040|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=534000|pts_time=5.933333|dts=534000|dts_time=5.933333|duration=6000|duration_time=0.066667|size=15|pos=15040|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=6000|duration_time=0.066667|size=15|pos=15228|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=6000|duration_time=0.066667|size=15|pos=15228|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=546000|pts_time=6.066667|dts=546000|dts_time=6.066667|duration=6000|duration_time=0.066667|size=15|pos=15416|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=546000|pts_time=6.066667|dts=546000|dts_time=6.066667|duration=6000|duration_time=0.066667|size=15|pos=15416|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=552000|pts_time=6.133333|dts=552000|dts_time=6.133333|duration=6000|duration_time=0.066667|size=16|pos=15604|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=552000|pts_time=6.133333|dts=552000|dts_time=6.133333|duration=6000|duration_time=0.066667|size=16|pos=15604|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:cca62b67 -packet|codec_type=video|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=6000|duration_time=0.066667|size=16|pos=15792|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=6000|duration_time=0.066667|size=16|pos=15792|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:27b943ef packet|codec_type=video|stream_index=0|pts=564000|pts_time=6.266667|dts=564000|dts_time=6.266667|duration=6000|duration_time=0.066667|size=16|pos=16356|flags=__|data_hash=CRC32:f7116111 stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|width=82|height=144|coded_width=82|coded_height=144|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=false|nal_length_size=0|id=0x100|r_frame_rate=15/1|avg_frame_rate=15/1|time_base=1/90000|start_pts=126000|start_time=1.400000|duration_ts=444000|duration=4.933333|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=74|extradata_size=35|extradata_hash=CRC32:e62cae27|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 From 028a6ed1a1cb125bf1b228eca4fead08a6d89334 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:19:33 -0600 Subject: [PATCH 578/894] lavc/videotoolboxenc: use common routine for pixfmt conversion --- libavcodec/videotoolboxenc.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index ebaa3ebdc8..1e7c164a97 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -29,6 +29,7 @@ #include "libavutil/avstring.h" #include "libavcodec/avcodec.h" #include "libavutil/pixdesc.h" +#include "libavutil/hwcontext_videotoolbox.h" #include "internal.h" #include #include "atsc_a53.h" @@ -797,25 +798,9 @@ static int get_cv_pixel_format(AVCodecContext* avctx, range != AVCOL_RANGE_JPEG; //MPEG range is used when no range is set - if (fmt == AV_PIX_FMT_NV12) { - *av_pixel_format = range == AVCOL_RANGE_JPEG ? - kCVPixelFormatType_420YpCbCr8BiPlanarFullRange : - kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; - } else if (fmt == AV_PIX_FMT_YUV420P) { - *av_pixel_format = range == AVCOL_RANGE_JPEG ? - kCVPixelFormatType_420YpCbCr8PlanarFullRange : - kCVPixelFormatType_420YpCbCr8Planar; - } else if (fmt == AV_PIX_FMT_BGRA) { - *av_pixel_format = kCVPixelFormatType_32BGRA; - } else if (fmt == AV_PIX_FMT_P010LE) { - *av_pixel_format = range == AVCOL_RANGE_JPEG ? - kCVPixelFormatType_420YpCbCr10BiPlanarFullRange : - kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; - } else { - return AVERROR(EINVAL); - } + *av_pixel_format = av_map_videotoolbox_format_from_pixfmt2(fmt, range == AVCOL_RANGE_JPEG); - return 0; + return *av_pixel_format ? 0 : AVERROR(EINVAL); } static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) { From 2acb13cb93b668d1b22bb541ab7e4583af2e7ea8 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:21:41 -0600 Subject: [PATCH 579/894] lavc/videotoolboxenc: don't access int64_t member as int --- libavcodec/videotoolboxenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 1e7c164a97..9857e55fdc 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -2618,7 +2618,7 @@ static const enum AVPixelFormat hevc_pix_fmts[] = { #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" }, { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2672,7 +2672,7 @@ const AVCodec ff_h264_videotoolbox_encoder = { }; static const AVOption hevc_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = HEVC_PROF_AUTO }, HEVC_PROF_AUTO, HEVC_PROF_COUNT, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = HEVC_PROF_AUTO }, HEVC_PROF_AUTO, HEVC_PROF_COUNT, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, From e55db79612cb39053442b69d911740ed47cb8347 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:24:59 -0600 Subject: [PATCH 580/894] lavc/videotoolboxenc: detect alpha more generically Fixes support for alpha in hardware input frames --- libavcodec/videotoolboxenc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 9857e55fdc..fa8f717a6c 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -406,14 +406,14 @@ static int count_nalus(size_t length_code_size, return 0; } -static CMVideoCodecType get_cm_codec_type(enum AVCodecID id, - enum AVPixelFormat fmt, +static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, double alpha_quality) { - switch (id) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX ? avctx->sw_pix_fmt : avctx->pix_fmt); + switch (avctx->codec_id) { case AV_CODEC_ID_H264: return kCMVideoCodecType_H264; case AV_CODEC_ID_HEVC: - if (fmt == AV_PIX_FMT_BGRA && alpha_quality > 0.0) { + if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpha_quality > 0.0) { return kCMVideoCodecType_HEVCWithAlpha; } return kCMVideoCodecType_HEVC; @@ -1376,7 +1376,7 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) CFNumberRef gamma_level = NULL; int status; - codec_type = get_cm_codec_type(avctx->codec_id, avctx->pix_fmt, vtctx->alpha_quality); + codec_type = get_cm_codec_type(avctx, vtctx->alpha_quality); if (!codec_type) { av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id); return AVERROR(EINVAL); From 7644c6224f327de23d2532d879aa36a31fe46bf4 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:26:41 -0600 Subject: [PATCH 581/894] lavc/videotoolboxenc: fix RGB support --- libavcodec/videotoolboxenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index fa8f717a6c..96e987c446 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -996,6 +996,7 @@ static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) { break; case AVCOL_SPC_UNSPECIFIED: + case AVCOL_SPC_RGB: *matrix = NULL; break; From c8323350f49dd95a67ceb42cef9cb012673f4598 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:28:52 -0600 Subject: [PATCH 582/894] lavc/videotoolboxenc: config-gate ATSC CC support --- libavcodec/videotoolboxenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 96e987c446..2dc4ce076c 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -2361,6 +2361,7 @@ static int vtenc_send_frame(AVCodecContext *avctx, return status; } +#if CONFIG_ATSC_A53 side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); if (vtctx->a53_cc && side_data && side_data->size) { sei = av_mallocz(sizeof(*sei)); @@ -2375,6 +2376,7 @@ static int vtenc_send_frame(AVCodecContext *avctx, } } } +#endif time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den); status = VTCompressionSessionEncodeFrame( From 30539394bb8b98ab6f7418e837006ef4c61d79f9 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:29:29 -0600 Subject: [PATCH 583/894] lavc/videotoolboxenc: vastly simplify get_cv_pixel_info No longer requires per-format switch cases. The frame==0 path was unused (and would've crashed anyway). --- libavcodec/videotoolboxenc.c | 71 ++++++++---------------------------- 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 2dc4ce076c..6f383b722d 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -2032,6 +2032,7 @@ static int get_cv_pixel_info( size_t *strides, size_t *contiguous_buf_size) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); VTEncContext *vtctx = avctx->priv_data; int av_format = frame->format; int av_color_range = frame->color_range; @@ -2039,6 +2040,9 @@ static int get_cv_pixel_info( int range_guessed; int status; + if (!desc) + return AVERROR(EINVAL); + status = get_cv_pixel_format(avctx, av_format, av_color_range, color, &range_guessed); if (status) { av_log(avctx, @@ -2063,63 +2067,18 @@ static int get_cv_pixel_info( } } - switch (av_format) { - case AV_PIX_FMT_NV12: - *plane_count = 2; + *plane_count = av_pix_fmt_count_planes(avctx->pix_fmt); - widths [0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : avctx->width; - - widths [1] = (avctx->width + 1) / 2; - heights[1] = (avctx->height + 1) / 2; - strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) & -2; - break; - - case AV_PIX_FMT_YUV420P: - *plane_count = 3; - - widths [0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : avctx->width; - - widths [1] = (avctx->width + 1) / 2; - heights[1] = (avctx->height + 1) / 2; - strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) / 2; - - widths [2] = (avctx->width + 1) / 2; - heights[2] = (avctx->height + 1) / 2; - strides[2] = frame ? frame->linesize[2] : (avctx->width + 1) / 2; - break; - - case AV_PIX_FMT_BGRA: - *plane_count = 1; - - widths [0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : avctx->width * 4; - break; - - case AV_PIX_FMT_P010LE: - *plane_count = 2; - widths[0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : (avctx->width * 2 + 63) & -64; - - widths[1] = (avctx->width + 1) / 2; - heights[1] = (avctx->height + 1) / 2; - strides[1] = frame ? frame->linesize[1] : ((avctx->width + 1) / 2 + 63) & -64; - break; - - default: - av_log( - avctx, - AV_LOG_ERROR, - "Could not get frame format info for color %d range %d.\n", - av_format, - av_color_range); - - return AVERROR(EINVAL); + for (i = 0; i < desc->nb_components; i++) { + int p = desc->comp[i].plane; + bool hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA); + bool isAlpha = hasAlpha && (p + 1 == *plane_count); + bool isChroma = (p != 0) && !isAlpha; + int shiftw = isChroma ? desc->log2_chroma_w : 0; + int shifth = isChroma ? desc->log2_chroma_h : 0; + widths[p] = (avctx->width + ((1 << shiftw) >> 1)) >> shiftw; + heights[p] = (avctx->height + ((1 << shifth) >> 1)) >> shifth; + strides[p] = frame->linesize[p]; } *contiguous_buf_size = 0; From 2bb5edc38cd4884b5f8a6f3907cd8aa8a297b2be Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:31:19 -0600 Subject: [PATCH 584/894] lavc/videotoolboxenc: add handling for non-NAL-based codecs --- libavcodec/videotoolboxenc.c | 160 +++++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 62 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 6f383b722d..0588e593ad 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -549,6 +549,7 @@ static int copy_param_sets( static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer) { + VTEncContext *vtctx = avctx->priv_data; CMVideoFormatDescriptionRef vid_fmt; size_t total_size; int status; @@ -559,23 +560,37 @@ static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer) return AVERROR_EXTERNAL; } - status = get_params_size(avctx, vid_fmt, &total_size); - if (status) { - av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n"); - return status; - } + if (vtctx->get_param_set_func) { + status = get_params_size(avctx, vid_fmt, &total_size); + if (status) { + av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n"); + return status; + } - avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) { - return AVERROR(ENOMEM); - } - avctx->extradata_size = total_size; + avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + return AVERROR(ENOMEM); + } + avctx->extradata_size = total_size; - status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size); + status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size); - if (status) { - av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n"); - return status; + if (status) { + av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n"); + return status; + } + } else { + CFDataRef data = CMFormatDescriptionGetExtension(vid_fmt, kCMFormatDescriptionExtension_VerbatimSampleDescription); + if (data && CFGetTypeID(data) == CFDataGetTypeID()) { + CFIndex size = CFDataGetLength(data); + + avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = size; + + CFDataGetBytes(data, CFRangeMake(0, size), avctx->extradata); + } } return 0; @@ -1936,62 +1951,83 @@ static int vtenc_cm_to_avpacket( CMTime dts; CMVideoFormatDescriptionRef vid_fmt; - vtenc_get_frame_info(sample_buffer, &is_key_frame); - status = get_length_code_size(avctx, sample_buffer, &length_code_size); - if (status) return status; - add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER); + if (vtctx->get_param_set_func) { + status = get_length_code_size(avctx, sample_buffer, &length_code_size); + if (status) return status; - if (add_header) { - vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer); - if (!vid_fmt) { - av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n"); + add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER); + + if (add_header) { + vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer); + if (!vid_fmt) { + av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n"); + return AVERROR_EXTERNAL; + } + + int status = get_params_size(avctx, vid_fmt, &header_size); + if (status) return status; + } + + status = count_nalus(length_code_size, sample_buffer, &nalu_count); + if(status) + return status; + + if (sei) { + size_t msg_size = get_sei_msg_bytes(sei, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35); + + sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1; + } + + in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer); + out_buf_size = header_size + + in_buf_size + + sei_nalu_size + + nalu_count * ((int)sizeof(start_code) - (int)length_code_size); + + status = ff_get_encode_buffer(avctx, pkt, out_buf_size, 0); + if (status < 0) + return status; + + if (add_header) { + status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size); + if(status) return status; + } + + status = copy_replace_length_codes( + avctx, + length_code_size, + sample_buffer, + sei, + pkt->data + header_size, + pkt->size - header_size + ); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status); + return status; + } + } else { + size_t len; + CMBlockBufferRef buf = CMSampleBufferGetDataBuffer(sample_buffer); + if (!buf) { + av_log(avctx, AV_LOG_ERROR, "Error getting block buffer\n"); return AVERROR_EXTERNAL; } - int status = get_params_size(avctx, vid_fmt, &header_size); - if (status) return status; - } + len = CMBlockBufferGetDataLength(buf); - status = count_nalus(length_code_size, sample_buffer, &nalu_count); - if(status) - return status; + status = ff_get_encode_buffer(avctx, pkt, len, 0); + if (status < 0) + return status; - if (sei) { - size_t msg_size = get_sei_msg_bytes(sei, - SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35); - - sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1; - } - - in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer); - out_buf_size = header_size + - in_buf_size + - sei_nalu_size + - nalu_count * ((int)sizeof(start_code) - (int)length_code_size); - - status = ff_get_encode_buffer(avctx, pkt, out_buf_size, 0); - if (status < 0) - return status; - - if (add_header) { - status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size); - if(status) return status; - } - - status = copy_replace_length_codes( - avctx, - length_code_size, - sample_buffer, - sei, - pkt->data + header_size, - pkt->size - header_size - ); - - if (status) { - av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status); - return status; + status = CMBlockBufferCopyDataBytes(buf, 0, len, pkt->data); + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status); + return AVERROR_EXTERNAL; + } } if (is_key_frame) { From 310a1c25e8248a1bfa8fcfa06bbeff64a41fbd79 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:32:30 -0600 Subject: [PATCH 585/894] lavc/Makefile: fix missing hevc_videotoolbox case --- libavcodec/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index fb90ecea84..0250f6cea9 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -403,6 +403,7 @@ OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o +OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ canopus.o From 88d804b7ffa20caab2e8e2809da974c41f7fd8fc Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 18:03:46 -0600 Subject: [PATCH 586/894] swscale: add P210/P410/P216/P416 output --- libswscale/output.c | 8 ++++++-- libswscale/utils.c | 16 ++++++++-------- libswscale/version.h | 2 +- tests/ref/fate/filter-pixdesc-p210be | 1 + tests/ref/fate/filter-pixdesc-p210le | 1 + tests/ref/fate/filter-pixdesc-p216be | 1 + tests/ref/fate/filter-pixdesc-p216le | 1 + tests/ref/fate/filter-pixdesc-p410be | 1 + tests/ref/fate/filter-pixdesc-p410le | 1 + tests/ref/fate/filter-pixdesc-p416be | 1 + tests/ref/fate/filter-pixdesc-p416le | 1 + tests/ref/fate/filter-pixfmts-copy | 8 ++++++++ tests/ref/fate/filter-pixfmts-crop | 8 ++++++++ tests/ref/fate/filter-pixfmts-field | 8 ++++++++ tests/ref/fate/filter-pixfmts-fieldorder | 8 ++++++++ tests/ref/fate/filter-pixfmts-hflip | 8 ++++++++ tests/ref/fate/filter-pixfmts-il | 8 ++++++++ tests/ref/fate/filter-pixfmts-null | 8 ++++++++ tests/ref/fate/filter-pixfmts-pad | 4 ++++ tests/ref/fate/filter-pixfmts-scale | 8 ++++++++ tests/ref/fate/filter-pixfmts-transpose | 4 ++++ tests/ref/fate/filter-pixfmts-vflip | 8 ++++++++ 22 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 tests/ref/fate/filter-pixdesc-p210be create mode 100644 tests/ref/fate/filter-pixdesc-p210le create mode 100644 tests/ref/fate/filter-pixdesc-p216be create mode 100644 tests/ref/fate/filter-pixdesc-p216le create mode 100644 tests/ref/fate/filter-pixdesc-p410be create mode 100644 tests/ref/fate/filter-pixdesc-p410le create mode 100644 tests/ref/fate/filter-pixdesc-p416be create mode 100644 tests/ref/fate/filter-pixdesc-p416le diff --git a/libswscale/output.c b/libswscale/output.c index 58b10f85a5..4b4b186be9 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -2563,14 +2563,18 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, enum AVPixelFormat dstFormat = c->dstFormat; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); - if (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P010BE) { + if (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P010BE || + dstFormat == AV_PIX_FMT_P210LE || dstFormat == AV_PIX_FMT_P210BE || + dstFormat == AV_PIX_FMT_P410LE || dstFormat == AV_PIX_FMT_P410BE) { *yuv2plane1 = isBE(dstFormat) ? yuv2p010l1_BE_c : yuv2p010l1_LE_c; *yuv2planeX = isBE(dstFormat) ? yuv2p010lX_BE_c : yuv2p010lX_LE_c; *yuv2nv12cX = yuv2p010cX_c; } else if (is16BPS(dstFormat)) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; - if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE) { + if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE || + dstFormat == AV_PIX_FMT_P216LE || dstFormat == AV_PIX_FMT_P216BE || + dstFormat == AV_PIX_FMT_P416LE || dstFormat == AV_PIX_FMT_P416BE) { *yuv2nv12cX = yuv2p016cX_c; } } else if (isNBPS(dstFormat)) { diff --git a/libswscale/utils.c b/libswscale/utils.c index 7158384f0b..c5ea8853d5 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -268,14 +268,14 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_Y210LE] = { 1, 0 }, [AV_PIX_FMT_X2RGB10LE] = { 1, 1 }, [AV_PIX_FMT_X2BGR10LE] = { 1, 1 }, - [AV_PIX_FMT_P210BE] = { 1, 0 }, - [AV_PIX_FMT_P210LE] = { 1, 0 }, - [AV_PIX_FMT_P410BE] = { 1, 0 }, - [AV_PIX_FMT_P410LE] = { 1, 0 }, - [AV_PIX_FMT_P216BE] = { 1, 0 }, - [AV_PIX_FMT_P216LE] = { 1, 0 }, - [AV_PIX_FMT_P416BE] = { 1, 0 }, - [AV_PIX_FMT_P416LE] = { 1, 0 }, + [AV_PIX_FMT_P210BE] = { 1, 1 }, + [AV_PIX_FMT_P210LE] = { 1, 1 }, + [AV_PIX_FMT_P410BE] = { 1, 1 }, + [AV_PIX_FMT_P410LE] = { 1, 1 }, + [AV_PIX_FMT_P216BE] = { 1, 1 }, + [AV_PIX_FMT_P216LE] = { 1, 1 }, + [AV_PIX_FMT_P416BE] = { 1, 1 }, + [AV_PIX_FMT_P416LE] = { 1, 1 }, }; void ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos, int filterSize, int16_t *filter, int dstW){ diff --git a/libswscale/version.h b/libswscale/version.h index 15ad54319c..8f7b56df9a 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #define LIBSWSCALE_VERSION_MAJOR 6 #define LIBSWSCALE_VERSION_MINOR 1 -#define LIBSWSCALE_VERSION_MICRO 101 +#define LIBSWSCALE_VERSION_MICRO 102 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ diff --git a/tests/ref/fate/filter-pixdesc-p210be b/tests/ref/fate/filter-pixdesc-p210be new file mode 100644 index 0000000000..b7d15ff93d --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p210be @@ -0,0 +1 @@ +pixdesc-p210be 9f3465e388d91beeb5cb7fe0011c5a67 diff --git a/tests/ref/fate/filter-pixdesc-p210le b/tests/ref/fate/filter-pixdesc-p210le new file mode 100644 index 0000000000..cdb96e9cf5 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p210le @@ -0,0 +1 @@ +pixdesc-p210le 9994fb3da38c83d3b5fd4994993ad0ae diff --git a/tests/ref/fate/filter-pixdesc-p216be b/tests/ref/fate/filter-pixdesc-p216be new file mode 100644 index 0000000000..657136996a --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p216be @@ -0,0 +1 @@ +pixdesc-p216be db5cabe6e5f1814a6d20e8398aec4785 diff --git a/tests/ref/fate/filter-pixdesc-p216le b/tests/ref/fate/filter-pixdesc-p216le new file mode 100644 index 0000000000..5ade1ee75f --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p216le @@ -0,0 +1 @@ +pixdesc-p216le 79d711ee3dac99e37c013d2073d90a2c diff --git a/tests/ref/fate/filter-pixdesc-p410be b/tests/ref/fate/filter-pixdesc-p410be new file mode 100644 index 0000000000..26ff981622 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p410be @@ -0,0 +1 @@ +pixdesc-p410be 85671676fa52d0350c918f45417f3c64 diff --git a/tests/ref/fate/filter-pixdesc-p410le b/tests/ref/fate/filter-pixdesc-p410le new file mode 100644 index 0000000000..826d98ea5e --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p410le @@ -0,0 +1 @@ +pixdesc-p410le 0b90a10af76240042876793a1dafa862 diff --git a/tests/ref/fate/filter-pixdesc-p416be b/tests/ref/fate/filter-pixdesc-p416be new file mode 100644 index 0000000000..5a23be5d72 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p416be @@ -0,0 +1 @@ +pixdesc-p416be a7d8a859ce47c3860e0fee31539a84b0 diff --git a/tests/ref/fate/filter-pixdesc-p416le b/tests/ref/fate/filter-pixdesc-p416le new file mode 100644 index 0000000000..25e733b69d --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p416le @@ -0,0 +1 @@ +pixdesc-p416le e0f93774f62dd3b261fb8637696f3773 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index 790b733112..b090739bd2 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -63,6 +63,14 @@ p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b +p210be 6df2a72ee297e53f9ac7f96acf0ef5d5 +p210le c06e4b76cf504e908128081f92b60ce2 +p216be 01d10b0d17c9f575b512dff36623a85b +p216le 2f634e1a3cd5c9c122e0f2ebadb3503d +p410be d9af5b8126ea7457edaf0c90ad0cb2b7 +p410le 527761e1f4381007044679710a352ecc +p416be fc5c1c45567de4a6bc9dbc8eef30116d +p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 rgb24 f4438057d046e6d98ade4e45294b21be diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index 3c410cbd6b..93353ad16a 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -61,6 +61,14 @@ p010be 8b2de2eb6b099bbf355bfc55a0694ddc p010le 373b50c766dfd0a8e79c9a73246d803a p016be 8b2de2eb6b099bbf355bfc55a0694ddc p016le 373b50c766dfd0a8e79c9a73246d803a +p210be b75f0e53a245e49af955fe210fc31bb8 +p210le 74fcd5a32eee687eebe002c884103963 +p216be 89cb3a4bd44ba624c1395e7ea6998dde +p216le e56f5e5b0d4460d56f27a5df8a4a1462 +p410be 37e56737c2421aa59a33c57423d58616 +p410le 75f910c7282d8065d97f502ba974c481 +p416be 13b2dc247bdb0ab7e5532f75048f5a2c +p416le ecb78b327ea5cfe1fff82945c1fca310 pal8 1f2cdc8e718f95c875dbc1034a688bfb rgb0 736646b70dd9a0be22b8da8041e35035 rgb24 c5fbbf816bb2000f4d2914e335698ef5 diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field index 37718d81d0..bcd1a0a45b 100644 --- a/tests/ref/fate/filter-pixfmts-field +++ b/tests/ref/fate/filter-pixfmts-field @@ -63,6 +63,14 @@ p010be a0311a09bba7383553267d2b3b9c075e p010le ee09a18aefa3ebe97715b3a7312cb8ff p016be a0311a09bba7383553267d2b3b9c075e p016le ee09a18aefa3ebe97715b3a7312cb8ff +p210be 341db7c98afd2767d48cdd72e224df2f +p210le 8d68f7655a3d76f2f8436bd25beb3973 +p216be 0dde930860e940dced179884c359f720 +p216le b573c0473a1368813d077487cc9bce0e +p410be 9e9a812b74854226271c5f7dc18c37b7 +p410le c981188c7fd9f32988a9f4732303f82b +p416be 203203e6788a80b52d2ca6ba629beb9c +p416le 1039b97bbe42ef0af1bc46d2c0fc819e pal8 0658c18dcd8d052d59dfbe23f5b368d9 rgb0 ca3fa6e865b91b3511c7f2bf62830059 rgb24 25ab271e26a5785be169578d99da5dd0 diff --git a/tests/ref/fate/filter-pixfmts-fieldorder b/tests/ref/fate/filter-pixfmts-fieldorder index 88780c05a7..761ef422b5 100644 --- a/tests/ref/fate/filter-pixfmts-fieldorder +++ b/tests/ref/fate/filter-pixfmts-fieldorder @@ -55,6 +55,14 @@ grayf32be 1aa7960131f880c54fe3c77f13448674 grayf32le 4029ac9d197f255794c1b9e416520fc7 nv24 4fdbef26042c77f012df114e666efdb2 nv42 59608290fece913e6b7d61edf581a529 +p210be 82958903f553e9d2d91549bd44559a5a +p210le 755363012d8801b96ead2e8b1b4d2ab8 +p216be 7159f11beb9138932f8d60b95efe96dc +p216le c0c888ab7bde56638732344076b3b2ba +p410be 411f89fadbee1ca43d2918eba583bea5 +p410le 2771dd3ae54a439921f51c29e79b6799 +p416be de6b84bd524e8fcfc251634cae416069 +p416le 2e73af44eb933580da59981176848dcc rgb0 2e3d8c91c7a83d451593dfd06607ff39 rgb24 b82577f8215d3dc2681be60f1da247af rgb444be 1c3afc3a0c53c51139c76504f59bb1f4 diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index 69c7b42b6e..1fc26b9fb5 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -61,6 +61,14 @@ p010be 744b13e44d39e1ff7588983fa03e0101 p010le a50b160346ab94f55a425065b57006f0 p016be 744b13e44d39e1ff7588983fa03e0101 p016le a50b160346ab94f55a425065b57006f0 +p210be 174cdf99f18658724e269bf38d2b653b +p210le b6982912b2376371edea4fccf99fe40c +p216be c58f03c6668ab0fbc3ee1a2da051e28c +p216le 1f5213bebf4c99634f57290f5ad99c0d +p410be aa40aa32be7aa353252bac70b5edc175 +p410le 1143c811c383e4461b1192dca0c74246 +p416be 8863e9156ee7edcb6b9e6ac01a2e338c +p416le a42b88cabc4395aa0bf1bcbbc876f48f pal8 5b7c77d99817b4f52339742a47de7797 rgb0 0092452f37d73da20193265ace0b7d57 rgb24 21571104e6091a689feabb7867e513dd diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il index 09fe072314..7e7f057afa 100644 --- a/tests/ref/fate/filter-pixfmts-il +++ b/tests/ref/fate/filter-pixfmts-il @@ -63,6 +63,14 @@ p010be 3df51286ef66b53e3e283dbbab582263 p010le eadcd8241e97e35b2b47d5eb2eaea6cd p016be 3df51286ef66b53e3e283dbbab582263 p016le eadcd8241e97e35b2b47d5eb2eaea6cd +p210be 4992fe87c600dfb177b1e2e6aa0f922c +p210le c695064fb9f2cc4e35957d4d649cc281 +p216be 98b73479f0ea9843768c162c449c3ac5 +p216le 77757390da383a90981e461d128d8789 +p410be a7183a01888b47a4d9f3672073c7ea7d +p410le 6cf3a3e199b327f4f013e0346410d7a8 +p416be 4dc4aebf18e09e8f8b49db90ae5ec127 +p416le 4990b51ff889d9ee23e68997f81c09f1 rgb0 cfaf68671e43248267d8cd50cae8c13f rgb24 88894f608cf33ba310f21996748d77a7 rgb444be 99d36d814988fb388aacdef575dacfcf diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index 790b733112..b090739bd2 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -63,6 +63,14 @@ p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b +p210be 6df2a72ee297e53f9ac7f96acf0ef5d5 +p210le c06e4b76cf504e908128081f92b60ce2 +p216be 01d10b0d17c9f575b512dff36623a85b +p216le 2f634e1a3cd5c9c122e0f2ebadb3503d +p410be d9af5b8126ea7457edaf0c90ad0cb2b7 +p410le 527761e1f4381007044679710a352ecc +p416be fc5c1c45567de4a6bc9dbc8eef30116d +p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 rgb24 f4438057d046e6d98ade4e45294b21be diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 57fa817cf5..1362d198b4 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -25,6 +25,10 @@ nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 nv24 193b9eadcc06ad5081609f76249b3e47 nv42 1738ad3c31c6c16e17679f5b09ce4677 +p210le 10b53de63b086de93c076d1d40f9da42 +p216le 0bbf778e1b6101a3f650ce0454a357f2 +p410le fcab6381bde9cd84b813925ff29be4d2 +p416le 6db094f8d7d27d7299bf9496ad66e2e0 rgb0 78d500c8361ab6423a4826a00268c908 rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index 1623e5c939..a5a4ac4cba 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -63,6 +63,14 @@ p010be 1d6726d94bf1385996a9a9840dd0e878 p010le 4b316f2b9e18972299beb73511278fa8 p016be 31e204018cbb53f8988c4e1174ea8ce9 p016le d5afe557f492a09317e525d7cb782f5b +p210be 42be1e97427247317444afa836969667 +p210le 04efb8f14a9d98417af40954a06aa187 +p216be caa0268d0f6779343a4432b6bc832c5b +p216le c8f65811f717a12706a598561c6df46d +p410be f580b8dcf5a826c94258eeba837fd874 +p410le 90fdd95ec4482c127d98307550a885c6 +p416be a1242f80d32705a757f4d3553542ae1f +p416le d91a0858ea8d2cf1ed29f179c9ad9666 pal8 29e10892009b2cfe431815ec3052ed3b rgb0 fbd27e98154efb7535826afed41e9bb0 rgb24 e022e741451e81f2ecce1c7240b93e87 diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose index 5117bcf763..dc3a0628ee 100644 --- a/tests/ref/fate/filter-pixfmts-transpose +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -61,6 +61,10 @@ p010be ad0de2cc9bff81688b182a870fcf7000 p010le e7ff5143595021246733ce6bd0a769e8 p016be ad0de2cc9bff81688b182a870fcf7000 p016le e7ff5143595021246733ce6bd0a769e8 +p410be 171453dc34dd3c77659914e2202c5aa6 +p410le 4e5f78dfccda9a6387e81354a56a033a +p416be ff09601f127101a8ce8997b9ae0fd6bf +p416le 7bb46e2aec65669a27502ec452941237 rgb0 31ea5da7fe779c6ea0a33f1d28aad918 rgb24 47654cabaaad79170b90afd5a02161dd rgb444be 3cac1f0c43a74d2a95eb02e187070845 diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 34c1a9c64f..7736e372ad 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -63,6 +63,14 @@ p010be 06e9354b6e0e38ba41736352cedc0bd5 p010le fd18d322bffbf5816902c13102872e22 p016be 06e9354b6e0e38ba41736352cedc0bd5 p016le fd18d322bffbf5816902c13102872e22 +p210be 328b09bb0c70571617901322b4194023 +p210le d71c2d4e483030ffd87fa6a68c83fce0 +p216be e4ab026532db1dfee38cedef384e605b +p216le 2c0a660762527706799c4705ca50a9c5 +p410be 637fb064c2ce173de5cf431aa9267914 +p410le 849308a1cdf41e055019cf311d1b2201 +p416be 8e9cf1b695c0a33b6094dd6c7b3722d9 +p416le 0991d7fff4e2caf36be219ecdd9619d4 pal8 450b0155d0f2d5628bf95a442db5f817 rgb0 56a7ea69541bcd27bef6a5615784722b rgb24 195e6dae1c3a488b9d3ceb7560d25d85 From 18192166e79134ec5fda1ea26d4fcf7b24345b33 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 17:33:46 -0600 Subject: [PATCH 587/894] lavc/videotoolboxenc: add ProRes support --- Changelog | 1 + configure | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/version.h | 2 +- libavcodec/videotoolboxenc.c | 120 +++++++++++++++++++++++++++++++++-- 6 files changed, 120 insertions(+), 7 deletions(-) diff --git a/Changelog b/Changelog index 11f5d358c0..a613e2c5a6 100644 --- a/Changelog +++ b/Changelog @@ -42,6 +42,7 @@ version : - vflip_vulkan, hflip_vulkan and flip_vulkan filters - adynamicequalizer audio filter - yadif_videotoolbox filter +- VideoToolbox ProRes encoder version 4.4: diff --git a/configure b/configure index 0ccd3bda11..41912abeb4 100755 --- a/configure +++ b/configure @@ -3306,6 +3306,8 @@ h264_videotoolbox_encoder_deps="pthreads" h264_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" +prores_videotoolbox_encoder_deps="pthreads" +prores_videotoolbox_encoder_select="videotoolbox_encoder" libaom_av1_decoder_deps="libaom" libaom_av1_encoder_deps="libaom" libaom_av1_encoder_select="extract_extradata_bsf" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0250f6cea9..9577062eec 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -565,6 +565,7 @@ OBJS-$(CONFIG_PRORES_DECODER) += proresdec2.o proresdsp.o proresdata.o OBJS-$(CONFIG_PRORES_ENCODER) += proresenc_anatoliy.o proresdata.o OBJS-$(CONFIG_PRORES_AW_ENCODER) += proresenc_anatoliy.o proresdata.o OBJS-$(CONFIG_PRORES_KS_ENCODER) += proresenc_kostya.o proresdata.o +OBJS-$(CONFIG_PRORES_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_PROSUMER_DECODER) += prosumer.o OBJS-$(CONFIG_PSD_DECODER) += psd.o OBJS-$(CONFIG_PTX_DECODER) += ptx.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 89d65266c8..d1e10197de 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -837,6 +837,7 @@ extern const AVCodec ff_mpeg4_cuvid_decoder; extern const AVCodec ff_mpeg4_mediacodec_decoder; extern const AVCodec ff_mpeg4_omx_encoder; extern const AVCodec ff_mpeg4_v4l2m2m_encoder; +extern const AVCodec ff_prores_videotoolbox_encoder; extern const AVCodec ff_vc1_cuvid_decoder; extern const AVCodec ff_vp8_cuvid_decoder; extern const AVCodec ff_vp8_mediacodec_decoder; diff --git a/libavcodec/version.h b/libavcodec/version.h index 8a0b94f5aa..db71fb1130 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 14 +#define LIBAVCODEC_VERSION_MINOR 15 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 0588e593ad..e33a16fab1 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -407,6 +407,7 @@ static int count_nalus(size_t length_code_size, } static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, + int64_t profile, double alpha_quality) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX ? avctx->sw_pix_fmt : avctx->pix_fmt); @@ -417,6 +418,31 @@ static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, return kCMVideoCodecType_HEVCWithAlpha; } return kCMVideoCodecType_HEVC; + case AV_CODEC_ID_PRORES: + switch (profile) { + case FF_PROFILE_PRORES_PROXY: + return MKBETAG('a','p','c','o'); // kCMVideoCodecType_AppleProRes422Proxy + case FF_PROFILE_PRORES_LT: + return MKBETAG('a','p','c','s'); // kCMVideoCodecType_AppleProRes422LT + case FF_PROFILE_PRORES_STANDARD: + return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 + case FF_PROFILE_PRORES_HQ: + return MKBETAG('a','p','c','h'); // kCMVideoCodecType_AppleProRes422HQ + case FF_PROFILE_PRORES_4444: + return MKBETAG('a','p','4','h'); // kCMVideoCodecType_AppleProRes4444 + case FF_PROFILE_PRORES_XQ: + return MKBETAG('a','p','4','x'); // kCMVideoCodecType_AppleProRes4444XQ + + default: + av_log(avctx, AV_LOG_ERROR, "Unknown profile ID: %"PRId64", using auto\n", profile); + case FF_PROFILE_UNKNOWN: + if (desc && + ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) || + desc->log2_chroma_w == 0)) + return MKBETAG('a','p','4','h'); // kCMVideoCodecType_AppleProRes4444 + else + return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 + } default: return 0; } } @@ -1102,7 +1128,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, kVTCompressionPropertyKey_Quality, quality_num); CFRelease(quality_num); - } else { + } else if (avctx->codec_id != AV_CODEC_ID_PRORES) { bit_rate_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bit_rate); @@ -1189,7 +1215,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (avctx->gop_size > 0) { + if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) { CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &avctx->gop_size); @@ -1338,7 +1364,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (!vtctx->has_b_frames) { + if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) { status = VTSessionSetProperty(vtctx->session, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse); @@ -1388,16 +1414,24 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) CFMutableDictionaryRef pixel_buffer_info; CMVideoCodecType codec_type; VTEncContext *vtctx = avctx->priv_data; - CFStringRef profile_level; + CFStringRef profile_level = NULL; CFNumberRef gamma_level = NULL; int status; - codec_type = get_cm_codec_type(avctx, vtctx->alpha_quality); + codec_type = get_cm_codec_type(avctx, vtctx->profile, vtctx->alpha_quality); if (!codec_type) { av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id); return AVERROR(EINVAL); } +#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) + if (avctx->codec_id == AV_CODEC_ID_PRORES) { + if (__builtin_available(macOS 10.10, *)) { + VTRegisterProfessionalVideoWorkflowVideoEncoders(); + } + } +#endif + vtctx->codec_id = avctx->codec_id; if (vtctx->codec_id == AV_CODEC_ID_H264) { @@ -1415,12 +1449,14 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) } if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); - } else { + } else if (vtctx->codec_id == AV_CODEC_ID_HEVC) { vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; if (!vtctx->get_param_set_func) return AVERROR(EINVAL); if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); // HEVC has b-byramid vtctx->has_b_frames = avctx->max_b_frames > 0 ? 2 : 0; + } else if (vtctx->codec_id == AV_CODEC_ID_PRORES) { + avctx->codec_tag = av_bswap32(codec_type); } enc_info = CFDictionaryCreateMutable( @@ -2601,6 +2637,39 @@ static const enum AVPixelFormat hevc_pix_fmts[] = { AV_PIX_FMT_NONE }; +static const enum AVPixelFormat prores_pix_fmts[] = { + AV_PIX_FMT_VIDEOTOOLBOX, + AV_PIX_FMT_YUV420P, +#ifdef kCFCoreFoundationVersionNumber10_7 + AV_PIX_FMT_NV12, + AV_PIX_FMT_AYUV64, +#endif + AV_PIX_FMT_UYVY422, +#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P010, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV16, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P210, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P216, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV24, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P410, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P416, +#endif + AV_PIX_FMT_BGRA, + AV_PIX_FMT_NONE +}; + #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM #define COMMON_OPTIONS \ { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \ @@ -2704,3 +2773,42 @@ const AVCodec ff_hevc_videotoolbox_encoder = { FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "videotoolbox", }; + +static const AVOption prores_options[] = { + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, FF_PROFILE_PRORES_XQ, VE, "profile" }, + { "auto", "Automatically determine based on input format", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, + { "proxy", "ProRes 422 Proxy", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_PROXY }, INT_MIN, INT_MAX, VE, "profile" }, + { "lt", "ProRes 422 LT", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_LT }, INT_MIN, INT_MAX, VE, "profile" }, + { "standard", "ProRes 422", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_STANDARD }, INT_MIN, INT_MAX, VE, "profile" }, + { "hq", "ProRes 422 HQ", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_HQ }, INT_MIN, INT_MAX, VE, "profile" }, + { "4444", "ProRes 4444", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_4444 }, INT_MIN, INT_MAX, VE, "profile" }, + { "xq", "ProRes 4444 XQ", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_XQ }, INT_MIN, INT_MAX, VE, "profile" }, + + COMMON_OPTIONS + { NULL }, +}; + +static const AVClass prores_videotoolbox_class = { + .class_name = "prores_videotoolbox", + .item_name = av_default_item_name, + .option = prores_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVCodec ff_prores_videotoolbox_encoder = { + .name = "prores_videotoolbox", + .long_name = NULL_IF_CONFIG_SMALL("VideoToolbox ProRes Encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_HARDWARE, + .priv_data_size = sizeof(VTEncContext), + .pix_fmts = prores_pix_fmts, + .init = vtenc_init, + .encode2 = vtenc_frame, + .close = vtenc_close, + .priv_class = &prores_videotoolbox_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "videotoolbox", +}; From 0e7684e55481197caa067c2b01d376b14a0ec251 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 16 Dec 2021 19:04:11 -0600 Subject: [PATCH 588/894] FATE: always pass -nostdin to ffmpeg This avoids making terminal config changes that may not be reverted properly during parallel testing. --- tests/Makefile | 2 +- tests/fate/ffmpeg.mak | 2 +- tests/fate/filter-audio.mak | 6 +++--- tests/fate/filter-video.mak | 4 ++-- tests/fate/fits.mak | 4 ++-- tests/fate/flvenc.mak | 2 +- tests/fate/hap.mak | 4 ++-- tests/fate/hevc.mak | 2 +- tests/fate/hlsenc.mak | 18 +++++++++--------- tests/fate/segment.mak | 6 +++--- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 1bf9a7a36b..87807ed31f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -40,7 +40,7 @@ tests/test_copy.ffmeta: tests/data $(M)cp -f $(SRC_PATH)/tests/test.ffmeta tests/test_copy.ffmeta tests/data/ffprobe-test.nut: ffmpeg$(PROGSSUF)$(EXESUF) tests/test_copy.ffmeta - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=sin(400*PI*2*t):d=0.125[out0]; testsrc=d=0.125[out1]; testsrc=s=100x100:d=0.125[out2]" \ -f ffmetadata -i $(TARGET_PATH)/tests/test_copy.ffmeta \ -flags +bitexact -fflags +bitexact -map 0:0 -map 0:1 -map 0:2 -map_metadata 1 \ diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 2a6a06642e..0b00bb5b23 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -141,7 +141,7 @@ fate-ffmpeg-streamloop: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/s tests/data/audio_shorter_than_video.nut: TAG = GEN tests/data/audio_shorter_than_video.nut: tests/data/vsynth_lena.yuv tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ -f lavfi -i "sine=1000:d=1" \ -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -threads 1 -c:a pcm_s16le -bitexact \ diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index db70f26438..f97318476f 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -201,7 +201,7 @@ fate-filter-compand: CMD = framecrc -auto_conversion_filters -i $(SRC) -frames:a tests/data/hls-list.m3u8: TAG = GEN tests/data/hls-list.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f segment -segment_time 10 -map 0 -flags +bitexact -codec:a mp2fixed \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/hls-out-%03d.ts 2>/dev/null @@ -211,10 +211,10 @@ fate-filter-hls: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hl tests/data/hls-list-append.m3u8: TAG = GEN tests/data/hls-list-append.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f segment -segment_time 10 -map 0 -flags +bitexact -codec:a mp2fixed \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/hls-append-out-%03d.ts 2>/dev/null; \ - $(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 10 -map 0 -flags +bitexact \ -hls_flags append_list -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls-append-out-%03d.ts \ $(TARGET_PATH)/tests/data/hls-list-append.m3u8 2>/dev/null diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 16f24a8422..7df79c70e9 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -677,7 +677,7 @@ fate-filter-tile: CMD = video_filter "tile=3x3:nb_frames=5:padding=7:margin=2" tests/pixfmts.mak: TAG = GEN tests/pixfmts.mak: ffmpeg$(PROGSSUF)$(EXESUF) | tests $(M)printf "PIXFMTS = " > $@ - $(Q)$(TARGET_EXEC) $(TARGET_PATH)/$< -pix_fmts list 2> /dev/null | awk 'NR > 8 && /^IO/ { printf $$2 " " }' >> $@ + $(Q)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin -pix_fmts list 2> /dev/null | awk 'NR > 8 && /^IO/ { printf $$2 " " }' >> $@ $(Q)printf "\n" >> $@ RUNNING_PIXFMTS_TESTS := $(filter check fate fate-list fate-filter fate-vfilter fate-filter-pixdesc%,$(MAKECMDGOALS)) @@ -838,7 +838,7 @@ fate-filter-metadata-avf-aphase-meter-out-of-phase: CMD = run $(FILTER_METADATA_ tests/data/file4560-override2rotate0.mov: TAG = GEN tests/data/file4560-override2rotate0.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/filter/sample-in-issue-505.mov -c copy -flags +bitexact -metadata:s:v:0 rotate=0 $(TARGET_PATH)/$@ -y 2>/dev/null FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER H264_DECODER AAC_FIXED_DECODER PCM_S16LE_ENCODER MOV_MUXER) += fate-filter-meta-4560-rotate0 diff --git a/tests/fate/fits.mak b/tests/fate/fits.mak index 8c2995a4c6..f16fc83266 100644 --- a/tests/fate/fits.mak +++ b/tests/fate/fits.mak @@ -1,6 +1,6 @@ tests/data/fits-multi.fits: TAG = GEN tests/data/fits-multi.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/gif/m4nb.gif \ -y $(TARGET_PATH)/$(@) 2>/dev/null @@ -14,7 +14,7 @@ map.tests/data/lena-gbrap16le.fits := rgba64 tests/data/lena%.fits: TAG = GEN tests/data/lena%.fits: NAME = $(map.$(@)) tests/data/lena%.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/png1/lena-$(map.$(@)).png \ -y $(TARGET_PATH)/$(@) 2>/dev/null diff --git a/tests/fate/flvenc.mak b/tests/fate/flvenc.mak index 4fdeeff4c1..9682f4a2ba 100644 --- a/tests/fate/flvenc.mak +++ b/tests/fate/flvenc.mak @@ -1,6 +1,6 @@ tests/data/add_keyframe_index.flv: TAG = GEN tests/data/add_keyframe_index.flv: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "sws_flags=+accurate_rnd+bitexact;testsrc=r=7:n=2:d=20" -sws_flags '+accurate_rnd+bitexact' -metadata "encoder=Lavf" -pix_fmt yuv420p -c:v flv1 -g 7 -f flv -flags +bitexact -fflags +bitexact \ -flvflags add_keyframe_index -idct simple -dct int -y $(TARGET_PATH)/tests/data/add_keyframe_index.flv 2> /dev/null; diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak index 1582971a6e..ba921798cc 100644 --- a/tests/fate/hap.mak +++ b/tests/fate/hap.mak @@ -46,13 +46,13 @@ fate-hapqa-extract-snappy16-to-hapalphaonly: CMD = framecrc -i $(TARGET_SAMPLES) #Test bsf conversion and mov tests/data/hapq_nosnappy.mov: TAG = GEN tests/data/hapq_nosnappy.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov -nostdin -c:v copy -bsf:v hapqa_extract=texture=color \ -tag:v HapY -metadata:s:v:0 encoder="HAPQ" $(TARGET_PATH)/$@ -y 2>/dev/null tests/data/hapalphaonly_nosnappy.mov: TAG = GEN tests/data/hapalphaonly_nosnappy.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov -nostdin -c:v copy -bsf:v hapqa_extract=texture=alpha \ -tag:v HapA -metadata:s:v:0 encoder="HAPAlpha Only" $(TARGET_PATH)/$@ -y 2>/dev/null diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index abe4264662..6528df6e27 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -244,7 +244,7 @@ FATE_HEVC_LARGE += fate-hevc-paramchange-yuv420p-yuv420p10 tests/data/hevc-mp4.mov: TAG = GEN tests/data/hevc-mp4.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/hevc-conformance/WPP_A_ericsson_MAIN10_2.bit -c copy -flags +bitexact $(TARGET_PATH)/$@ -y 2>/dev/null FATE_HEVC-$(call ALLYES, HEVC_DEMUXER MOV_DEMUXER HEVC_MP4TOANNEXB_BSF MOV_MUXER HEVC_MUXER) += fate-hevc-bsf-mp4toannexb diff --git a/tests/fate/hlsenc.mak b/tests/fate/hlsenc.mak index aff81a83fc..7df74f1f63 100644 --- a/tests/fate/hlsenc.mak +++ b/tests/fate/hlsenc.mak @@ -1,6 +1,6 @@ tests/data/live_no_endlist.m3u8: TAG = GEN tests/data/live_no_endlist.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -v verbose -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 3 -map 0 \ -hls_flags omit_endlist -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/live_no_endlist_%03d.ts \ $(TARGET_PATH)/tests/data/live_no_endlist.m3u8 2>/dev/null @@ -14,7 +14,7 @@ fate-hls-live-no-endlist: REF = e038bb8e65d4c1745b9b3ed643e607a3 tests/data/live_last_endlist.m3u8: TAG = GEN tests/data/live_last_endlist.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -v verbose -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 3 -map 0 \ -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/live_last_endlist_%03d.ts \ $(TARGET_PATH)/tests/data/live_last_endlist.m3u8 2>/dev/null @@ -29,7 +29,7 @@ fate-hls-live-last-endlist: REF = 2ca8567092dcf01e37bedd50454d1ab7 tests/data/live_endlist.m3u8: TAG = GEN tests/data/live_endlist.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 3 -map 0 \ -hls_list_size 0 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/live_endlist_%d.ts \ $(TARGET_PATH)/tests/data/live_endlist.m3u8 2>/dev/null @@ -43,7 +43,7 @@ fate-hls-live-endlist: REF = e189ce781d9c87882f58e3929455167b tests/data/hls_segment_size.m3u8: TAG = GEN tests/data/hls_segment_size.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_segment_size 300000 -map 0 \ -hls_list_size 0 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_segment_size_%d.ts \ $(TARGET_PATH)/tests/data/hls_segment_size.m3u8 2>/dev/null @@ -54,7 +54,7 @@ fate-hls-segment-size: CMD = framecrc -auto_conversion_filters -flags +bitexact tests/data/hls_segment_single.m3u8: TAG = GEN tests/data/hls_segment_single.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_flags single_file -map 0 \ -hls_list_size 0 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_segment_single.ts \ $(TARGET_PATH)/tests/data/hls_segment_single.m3u8 2>/dev/null @@ -65,7 +65,7 @@ fate-hls-segment-single: CMD = framecrc -auto_conversion_filters -flags +bitexac tests/data/hls_init_time.m3u8: TAG = GEN tests/data/hls_init_time.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=11" -f hls -hls_init_time 1 -hls_time 3 -map 0 \ -hls_list_size 5 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_init_time_%d.ts \ $(TARGET_PATH)/tests/data/hls_init_time.m3u8 2>/dev/null @@ -76,7 +76,7 @@ fate-hls-init-time: CMD = framecrc -auto_conversion_filters -flags +bitexact -i tests/data/hls_list_size.m3u8: TAG = GEN tests/data/hls_list_size.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 4 -map 0 \ -hls_list_size 4 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_list_size_%d.ts \ $(TARGET_PATH)/tests/data/hls_list_size.m3u8 2>/dev/null @@ -87,7 +87,7 @@ fate-hls-list-size: CMD = framecrc -auto_conversion_filters -flags +bitexact -i tests/data/hls_fmp4.m3u8: TAG = GEN tests/data/hls_fmp4.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -re -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=5" -map 0 -codec:a mp2fixed \ -hls_segment_type mpegts -hls_fmp4_init_filename now.mp4 -hls_list_size 0 \ -hls_time 1 -hls_segment_filename "$(TARGET_PATH)/tests/data/hls_fmp4_%d.m4s" \ @@ -99,7 +99,7 @@ fate-hls-fmp4: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TAR tests/data/hls_fmp4_ac3.m3u8: TAG = GEN tests/data/hls_fmp4_ac3.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -stream_loop 4 -i $(SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 -c copy -map 0 \ -hls_segment_type fmp4 -hls_fmp4_init_filename now_ac3.mp4 -hls_list_size 0 \ -hls_time 2 -hls_segment_filename "$(TARGET_PATH)/tests/data/hls_fmp4_ac3_%d.m4s" \ diff --git a/tests/fate/segment.mak b/tests/fate/segment.mak index ddefbed3bd..88866fc9bb 100644 --- a/tests/fate/segment.mak +++ b/tests/fate/segment.mak @@ -1,20 +1,20 @@ tests/data/mp4-to-ts.m3u8: TAG = GEN tests/data/mp4-to-ts.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 \ -f ssegment -segment_time 1 -map 0 -flags +bitexact -codec copy \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/mp4-to-ts-%03d.ts 2>/dev/null tests/data/adts-to-mkv.m3u8: TAG = GEN tests/data/adts-to-mkv.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a \ -f segment -segment_time 1 -map 0 -flags +bitexact -codec copy -segment_format_options live=1 \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/adts-to-mkv-%03d.mkv 2>/dev/null tests/data/adts-to-mkv-header.mkv: TAG = GEN tests/data/adts-to-mkv-header.mkv: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a \ -f segment -segment_time 1 -map 0 -flags +bitexact -codec copy -segment_format_options live=1 \ -segment_header_filename $(TARGET_PATH)/tests/data/adts-to-mkv-header.mkv \ From 9a890e49b66d611c1c97347c9529ae85920bd5a1 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 04:55:44 -0600 Subject: [PATCH 589/894] lavc/proresdec: fix threaded hwaccel decode --- libavcodec/proresdec2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 719194f21e..d2d881a3dd 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -807,6 +807,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) return ret; + ff_thread_finish_setup(avctx); if (avctx->hwaccel) { ret = avctx->hwaccel->start_frame(avctx, NULL, 0); @@ -856,6 +857,18 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } +#if HAVE_THREADS +static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + ProresContext *csrc = src->priv_data; + ProresContext *cdst = dst->priv_data; + + cdst->pix_fmt = csrc->pix_fmt; + + return 0; +} +#endif + const AVCodec ff_prores_decoder = { .name = "prores", .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), @@ -865,6 +878,7 @@ const AVCodec ff_prores_decoder = { .init = decode_init, .close = decode_close, .decode = decode_frame, + .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, From 69bd95dcd8d09ecc04f994a239c1d3da62ec38d6 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 04:59:13 -0600 Subject: [PATCH 590/894] lavu/videotoolbox: expose conversion routines for color parameters Also fixes symbol lookup errors on older macOS when built with a newer SDK, introduced in 6cab5206b0ad94990c435cb7c5cf3b29675e0231 --- doc/APIchanges | 6 + libavutil/hwcontext_videotoolbox.c | 249 +++++++++++++++-------------- libavutil/hwcontext_videotoolbox.h | 25 +++ 3 files changed, 158 insertions(+), 122 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index ac75040274..061883f5a4 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,12 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-xx - xxxxxxxxxx - lavu 57.13.100 - hwcontext_videotoolbox.h + Add av_map_videotoolbox_chroma_loc_from_av + Add av_map_videotoolbox_color_matrix_from_av + Add av_map_videotoolbox_color_primaries_from_av + Add av_map_videotoolbox_color_trc_from_av + 2021-12-21 - xxxxxxxxxx - lavu 57.12.100 - cpu.h Add AV_CPU_FLAG_SLOW_GATHER. diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index e9567bbf44..353e09b57f 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -318,7 +318,7 @@ static void vt_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) CVPixelBufferUnlockBaseAddress(pixbuf, (uintptr_t)hwmap->priv); } -static int vt_pixbuf_set_par(AVHWFramesContext *hwfc, +static int vt_pixbuf_set_par(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { CFMutableDictionaryRef par = NULL; @@ -375,31 +375,30 @@ static int vt_pixbuf_set_par(AVHWFramesContext *hwfc, return 0; } -static int vt_pixbuf_set_chromaloc(AVHWFramesContext *hwfc, +CFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc) +{ + switch (loc) { + case AVCHROMA_LOC_LEFT: + return kCVImageBufferChromaLocation_Left; + case AVCHROMA_LOC_CENTER: + return kCVImageBufferChromaLocation_Center; + case AVCHROMA_LOC_TOP: + return kCVImageBufferChromaLocation_Top; + case AVCHROMA_LOC_BOTTOM: + return kCVImageBufferChromaLocation_Bottom; + case AVCHROMA_LOC_TOPLEFT: + return kCVImageBufferChromaLocation_TopLeft; + case AVCHROMA_LOC_BOTTOMLEFT: + return kCVImageBufferChromaLocation_BottomLeft; + default: + return NULL; + } +} + +static int vt_pixbuf_set_chromaloc(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { - CFStringRef loc = NULL; - - switch (src->chroma_location) { - case AVCHROMA_LOC_LEFT: - loc = kCVImageBufferChromaLocation_Left; - break; - case AVCHROMA_LOC_CENTER: - loc = kCVImageBufferChromaLocation_Center; - break; - case AVCHROMA_LOC_TOP: - loc = kCVImageBufferChromaLocation_Top; - break; - case AVCHROMA_LOC_BOTTOM: - loc = kCVImageBufferChromaLocation_Bottom; - break; - case AVCHROMA_LOC_TOPLEFT: - loc = kCVImageBufferChromaLocation_TopLeft; - break; - case AVCHROMA_LOC_BOTTOMLEFT: - loc = kCVImageBufferChromaLocation_BottomLeft; - break; - } + CFStringRef loc = av_map_videotoolbox_chroma_loc_from_av(src->chroma_location); if (loc) { CVBufferSetAttachment( @@ -412,109 +411,115 @@ static int vt_pixbuf_set_chromaloc(AVHWFramesContext *hwfc, return 0; } -static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, +CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space) +{ + switch (space) { + case AVCOL_SPC_BT2020_CL: + case AVCOL_SPC_BT2020_NCL: +#if HAVE_KCVIMAGEBUFFERYCBCRMATRIX_ITU_R_2020 + if (__builtin_available(macOS 10.11, iOS 9, *)) + return kCVImageBufferYCbCrMatrix_ITU_R_2020; +#endif + return CFSTR("ITU_R_2020"); + case AVCOL_SPC_BT470BG: + case AVCOL_SPC_SMPTE170M: + return kCVImageBufferYCbCrMatrix_ITU_R_601_4; + case AVCOL_SPC_BT709: + return kCVImageBufferYCbCrMatrix_ITU_R_709_2; + case AVCOL_SPC_SMPTE240M: + return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; + case AVCOL_SPC_UNSPECIFIED: + default: + return NULL; + } +} + +CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri) +{ + switch (pri) { + case AVCOL_PRI_BT2020: +#if HAVE_KCVIMAGEBUFFERCOLORPRIMARIES_ITU_R_2020 + if (__builtin_available(macOS 10.11, iOS 9, *)) + return kCVImageBufferColorPrimaries_ITU_R_2020; +#endif + return CFSTR("ITU_R_2020"); + case AVCOL_PRI_BT709: + return kCVImageBufferColorPrimaries_ITU_R_709_2; + case AVCOL_PRI_SMPTE170M: + return kCVImageBufferColorPrimaries_SMPTE_C; + case AVCOL_PRI_BT470BG: + return kCVImageBufferColorPrimaries_EBU_3213; + case AVCOL_PRI_UNSPECIFIED: + default: + return NULL; + } +} + +CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc) +{ + + switch (trc) { + case AVCOL_TRC_SMPTE2084: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ + if (__builtin_available(macOS 10.13, iOS 11, *)) + return kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; +#endif + return CFSTR("SMPTE_ST_2084_PQ"); + case AVCOL_TRC_BT2020_10: + case AVCOL_TRC_BT2020_12: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2020 + if (__builtin_available(macOS 10.11, iOS 9, *)) + return kCVImageBufferTransferFunction_ITU_R_2020; +#endif + return CFSTR("ITU_R_2020"); + case AVCOL_TRC_BT709: + return kCVImageBufferTransferFunction_ITU_R_709_2; + case AVCOL_TRC_SMPTE240M: + return kCVImageBufferTransferFunction_SMPTE_240M_1995; + case AVCOL_TRC_SMPTE428: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_428_1 + if (__builtin_available(macOS 10.12, iOS 10, *)) + return kCVImageBufferTransferFunction_SMPTE_ST_428_1; +#endif + return CFSTR("SMPTE_ST_428_1"); + case AVCOL_TRC_ARIB_STD_B67: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, *)) + return kCVImageBufferTransferFunction_ITU_R_2100_HLG; +#endif + return CFSTR("ITU_R_2100_HLG"); + case AVCOL_TRC_GAMMA22: + return kCVImageBufferTransferFunction_UseGamma; + case AVCOL_TRC_GAMMA28: + return kCVImageBufferTransferFunction_UseGamma; + default: + case AVCOL_TRC_UNSPECIFIED: + return NULL; + } +} + +static int vt_pixbuf_set_colorspace(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { CFStringRef colormatrix = NULL, colorpri = NULL, colortrc = NULL; Float32 gamma = 0; - switch (src->colorspace) { - case AVCOL_SPC_BT2020_CL: - case AVCOL_SPC_BT2020_NCL: -#if HAVE_KCVIMAGEBUFFERYCBCRMATRIX_ITU_R_2020 - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_2020; -#else - colormatrix = CFSTR("ITU_R_2020"); -#endif - break; - case AVCOL_SPC_BT470BG: - case AVCOL_SPC_SMPTE170M: - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4; - break; - case AVCOL_SPC_BT709: - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2; - break; - case AVCOL_SPC_SMPTE240M: - colormatrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; - break; - case AVCOL_SPC_UNSPECIFIED: - break; - default: - av_log(hwfc, AV_LOG_WARNING, "Color space %s is not supported.\n", av_color_space_name(src->colorspace)); - } + colormatrix = av_map_videotoolbox_color_matrix_from_av(src->colorspace); + if (!colormatrix && src->colorspace != AVCOL_SPC_UNSPECIFIED) + av_log(log_ctx, AV_LOG_WARNING, "Color space %s is not supported.\n", av_color_space_name(src->colorspace)); - switch (src->color_primaries) { - case AVCOL_PRI_BT2020: -#if HAVE_KCVIMAGEBUFFERCOLORPRIMARIES_ITU_R_2020 - colorpri = kCVImageBufferColorPrimaries_ITU_R_2020; -#else - colorpri = CFSTR("ITU_R_2020"); -#endif - break; - case AVCOL_PRI_BT709: - colorpri = kCVImageBufferColorPrimaries_ITU_R_709_2; - break; - case AVCOL_PRI_SMPTE170M: - colorpri = kCVImageBufferColorPrimaries_SMPTE_C; - break; - case AVCOL_PRI_BT470BG: - colorpri = kCVImageBufferColorPrimaries_EBU_3213; - break; - case AVCOL_PRI_UNSPECIFIED: - break; - default: - av_log(hwfc, AV_LOG_WARNING, "Color primaries %s is not supported.\n", av_color_primaries_name(src->color_primaries)); - } + colorpri = av_map_videotoolbox_color_primaries_from_av(src->color_primaries); + if (!colorpri && src->color_primaries != AVCOL_PRI_UNSPECIFIED) + av_log(log_ctx, AV_LOG_WARNING, "Color primaries %s is not supported.\n", av_color_primaries_name(src->color_primaries)); - switch (src->color_trc) { - case AVCOL_TRC_SMPTE2084: -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ - colortrc = kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; -#else - colortrc = CFSTR("SMPTE_ST_2084_PQ"); -#endif - break; - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2020 - colortrc = kCVImageBufferTransferFunction_ITU_R_2020; -#else - colortrc = CFSTR("ITU_R_2020"); -#endif - break; - case AVCOL_TRC_BT709: - colortrc = kCVImageBufferTransferFunction_ITU_R_709_2; - break; - case AVCOL_TRC_SMPTE240M: - colortrc = kCVImageBufferTransferFunction_SMPTE_240M_1995; - break; - case AVCOL_TRC_SMPTE428: -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_428_1 - colortrc = kCVImageBufferTransferFunction_SMPTE_ST_428_1; -#else - colortrc = CFSTR("SMPTE_ST_428_1"); -#endif - break; - case AVCOL_TRC_ARIB_STD_B67: -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG - colortrc = kCVImageBufferTransferFunction_ITU_R_2100_HLG; -#else - colortrc = CFSTR("ITU_R_2100_HLG"); -#endif - break; - case AVCOL_TRC_GAMMA22: + colortrc = av_map_videotoolbox_color_trc_from_av(src->color_trc); + if (!colortrc && src->color_trc != AVCOL_TRC_UNSPECIFIED) + av_log(log_ctx, AV_LOG_WARNING, "Color transfer function %s is not supported.\n", av_color_transfer_name(src->color_trc)); + + if (src->color_trc == AVCOL_TRC_GAMMA22) gamma = 2.2; - colortrc = kCVImageBufferTransferFunction_UseGamma; - break; - case AVCOL_TRC_GAMMA28: + else if (src->color_trc == AVCOL_TRC_GAMMA28) gamma = 2.8; - colortrc = kCVImageBufferTransferFunction_UseGamma; - break; - case AVCOL_TRC_UNSPECIFIED: - break; - default: - av_log(hwfc, AV_LOG_WARNING, "Color transfer function %s is not supported.\n", av_color_transfer_name(src->color_trc)); - } if (colormatrix) { CVBufferSetAttachment( @@ -550,17 +555,17 @@ static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, return 0; } -static int vt_pixbuf_set_attachments(AVHWFramesContext *hwfc, +static int vt_pixbuf_set_attachments(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { int ret; - ret = vt_pixbuf_set_par(hwfc, pixbuf, src); + ret = vt_pixbuf_set_par(log_ctx, pixbuf, src); if (ret < 0) return ret; - ret = vt_pixbuf_set_colorspace(hwfc, pixbuf, src); + ret = vt_pixbuf_set_colorspace(log_ctx, pixbuf, src); if (ret < 0) return ret; - ret = vt_pixbuf_set_chromaloc(hwfc, pixbuf, src); + ret = vt_pixbuf_set_chromaloc(log_ctx, pixbuf, src); if (ret < 0) return ret; return 0; diff --git a/libavutil/hwcontext_videotoolbox.h b/libavutil/hwcontext_videotoolbox.h index 62cde07c51..916899e97d 100644 --- a/libavutil/hwcontext_videotoolbox.h +++ b/libavutil/hwcontext_videotoolbox.h @@ -60,4 +60,29 @@ uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt); */ uint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range); +/** + * Convert an AVChromaLocation to a VideoToolbox/CoreVideo chroma location string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc); + +/** + * Convert an AVColorSpace to a VideoToolbox/CoreVideo color matrix string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space); + +/** + * Convert an AVColorPrimaries to a VideoToolbox/CoreVideo color primaries string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri); + +/** + * Convert an AVColorTransferCharacteristic to a VideoToolbox/CoreVideo color transfer + * function string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc); + #endif /* AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H */ From b7e1ec7bda90f979e29f7e06dcd73b5e38ed3ac0 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 05:02:18 -0600 Subject: [PATCH 591/894] lavu/videotoolbox: expose routine to set CVPixelBufferRef metadata --- doc/APIchanges | 3 +++ libavutil/hwcontext_videotoolbox.c | 6 ++++++ libavutil/hwcontext_videotoolbox.h | 7 +++++++ libavutil/version.h | 2 +- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 061883f5a4..670a59329e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-xx - xxxxxxxxxx - lavu 57.13.100 - hwcontext_videotoolbox.h + Add av_vt_pixbuf_set_attachments + 2021-12-xx - xxxxxxxxxx - lavu 57.13.100 - hwcontext_videotoolbox.h Add av_map_videotoolbox_chroma_loc_from_av Add av_map_videotoolbox_color_matrix_from_av diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index 353e09b57f..eff5fdbef1 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -571,6 +571,12 @@ static int vt_pixbuf_set_attachments(void *log_ctx, return 0; } +int av_vt_pixbuf_set_attachments(void *log_ctx, + CVPixelBufferRef pixbuf, const AVFrame *src) +{ + return vt_pixbuf_set_attachments(log_ctx, pixbuf, src); +} + static int vt_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags) { diff --git a/libavutil/hwcontext_videotoolbox.h b/libavutil/hwcontext_videotoolbox.h index 916899e97d..b6bdcf243d 100644 --- a/libavutil/hwcontext_videotoolbox.h +++ b/libavutil/hwcontext_videotoolbox.h @@ -85,4 +85,11 @@ CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pr */ CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc); +/** + * Update a CVPixelBufferRef's metadata to based on an AVFrame. + * Returns 0 if no known equivalent was found. + */ +int av_vt_pixbuf_set_attachments(void *log_ctx, + CVPixelBufferRef pixbuf, const struct AVFrame *src); + #endif /* AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 668f9206fe..3cac09cb96 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 12 +#define LIBAVUTIL_VERSION_MINOR 13 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 5afc5661ac042f04111305c34020e9b0ff87400f Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 06:46:32 -0600 Subject: [PATCH 592/894] lavu/hwcontext_videotoolbox: use OS-provided mapping routines when available --- libavutil/hwcontext_videotoolbox.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index eff5fdbef1..0a8dbe9f33 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -428,8 +428,12 @@ CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space) return kCVImageBufferYCbCrMatrix_ITU_R_709_2; case AVCOL_SPC_SMPTE240M: return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; - case AVCOL_SPC_UNSPECIFIED: default: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) + return CVYCbCrMatrixGetStringForIntegerCodePoint(space); +#endif + case AVCOL_SPC_UNSPECIFIED: return NULL; } } @@ -449,8 +453,12 @@ CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pr return kCVImageBufferColorPrimaries_SMPTE_C; case AVCOL_PRI_BT470BG: return kCVImageBufferColorPrimaries_EBU_3213; - case AVCOL_PRI_UNSPECIFIED: default: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) + return CVColorPrimariesGetStringForIntegerCodePoint(pri); +#endif + case AVCOL_PRI_UNSPECIFIED: return NULL; } } @@ -493,6 +501,10 @@ CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteri case AVCOL_TRC_GAMMA28: return kCVImageBufferTransferFunction_UseGamma; default: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) + return CVTransferFunctionGetStringForIntegerCodePoint(trc); +#endif case AVCOL_TRC_UNSPECIFIED: return NULL; } From b04601ed6ab91c4f6f5cbe08050ea1e4d001cec4 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 05:02:47 -0600 Subject: [PATCH 593/894] lavc/videotoolbox: set attachments on decoded buffers VideoToolbox internally sets all the colorspace parameters to BT709, regardless of what the bitstream actually indicates, so we need to replace that with what we've parsed. --- libavcodec/videotoolbox.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 519f55a9ab..69beb3881f 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -90,6 +90,7 @@ int ff_videotoolbox_buffer_copy(VTContext *vtctx, static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) { + int ret; VTHWFrame *ref = (VTHWFrame *)frame->buf[0]->data; if (!ref->pixbuf) { @@ -103,6 +104,9 @@ static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) frame->crop_top = 0; frame->crop_bottom = 0; + if ((ret = av_vt_pixbuf_set_attachments(avctx, ref->pixbuf, frame)) < 0) + return ret; + frame->data[3] = (uint8_t*)ref->pixbuf; if (ref->hw_frames_ctx) { From 802c0515067fa3f5a67feb56241789dfcfb1ad09 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 14:35:17 -0600 Subject: [PATCH 594/894] libavcodec/videotoolboxenc: use the correct types for options These are all set by AV_OPT_TYPE_INT or AV_OPT_TYPE_BOOL; the only reason they worked before was that this is only used on little-endian. --- libavcodec/videotoolboxenc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index e33a16fab1..a2f5aa9be9 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -227,14 +227,14 @@ typedef struct VTEncContext { int64_t dts_delta; int64_t profile; - int64_t level; - int64_t entropy; - int64_t realtime; - int64_t frames_before; - int64_t frames_after; + int level; + int entropy; + int realtime; + int frames_before; + int frames_after; - int64_t allow_sw; - int64_t require_sw; + int allow_sw; + int require_sw; double alpha_quality; bool flushing; From 4778ab2b1fa993457bb3657de56a12dc9a55f3a0 Mon Sep 17 00:00:00 2001 From: rcombs Date: Sat, 18 Dec 2021 14:39:19 -0600 Subject: [PATCH 595/894] lavc/videotoolboxenc: explicitly set realtime=false On some encoders, this defaults to true, which can result in encode speed being _limited_ to only slightly above realtime (as a power-saving measure), so we need a way to disable it. --- libavcodec/videotoolboxenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index a2f5aa9be9..418ff00b8d 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -1389,10 +1389,10 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (vtctx->realtime) { + if (vtctx->realtime >= 0) { status = VTSessionSetProperty(vtctx->session, compat_keys.kVTCompressionPropertyKey_RealTime, - kCFBooleanTrue); + vtctx->realtime ? kCFBooleanTrue : kCFBooleanFalse); if (status) { av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status); @@ -2677,7 +2677,7 @@ static const enum AVPixelFormat prores_pix_fmts[] = { { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \ { .i64 = 0 }, 0, 1, VE }, \ { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \ - OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ + OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, \ { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \ OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \ From 942f94e830f5821fa61514eebfc6033f65a71fd8 Mon Sep 17 00:00:00 2001 From: rcombs Date: Mon, 20 Dec 2021 17:21:05 -0600 Subject: [PATCH 596/894] configure: fix setting OBJCCFLAGS We call this OBJCFLAGS in help text, but common.mak looks for OBJCCFLAGS. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 41912abeb4..b190b57124 100755 --- a/configure +++ b/configure @@ -7643,7 +7643,7 @@ LN_S=$ln_s CPPFLAGS=$CPPFLAGS CFLAGS=$CFLAGS CXXFLAGS=$CXXFLAGS -OBJCFLAGS=$OBJCFLAGS +OBJCCFLAGS=$OBJCFLAGS ASFLAGS=$ASFLAGS NVCCFLAGS=$nvccflags AS_C=$AS_C From bc63ef354a24ba9b56ecc7722aa485b991382771 Mon Sep 17 00:00:00 2001 From: rcombs Date: Mon, 20 Dec 2021 17:21:52 -0600 Subject: [PATCH 597/894] configure: fix .d generation for C++ and Obj-C files --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index b190b57124..df7f5df4d9 100755 --- a/configure +++ b/configure @@ -7693,6 +7693,8 @@ ASDEP_FLAGS=$ASDEP_FLAGS X86ASMDEP=$X86ASMDEP X86ASMDEP_FLAGS=$X86ASMDEP_FLAGS CC_DEPFLAGS=$CC_DEPFLAGS +CXX_DEPFLAGS=$CXX_DEPFLAGS +OBJCC_DEPFLAGS=$OBJC_DEPFLAGS AS_DEPFLAGS=$AS_DEPFLAGS X86ASM_DEPFLAGS=$X86ASM_DEPFLAGS HOSTCC=$host_cc From 2d16182e7d99a77634f2518966beb8c41b7c7978 Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 21 Dec 2021 02:34:25 -0600 Subject: [PATCH 598/894] lavfi/metal: don't use braced-include for internal headers --- libavfilter/metal/utils.m | 2 +- libavfilter/vf_yadif_videotoolbox.m | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m index 759ebedfba..f831502065 100644 --- a/libavfilter/metal/utils.m +++ b/libavfilter/metal/utils.m @@ -17,7 +17,7 @@ */ #include "libavutil/log.h" -#include +#include "utils.h" void ff_metal_compute_encoder_dispatch(id device, id pipeline, diff --git a/libavfilter/vf_yadif_videotoolbox.m b/libavfilter/vf_yadif_videotoolbox.m index af83a73e89..65f155982e 100644 --- a/libavfilter/vf_yadif_videotoolbox.m +++ b/libavfilter/vf_yadif_videotoolbox.m @@ -20,11 +20,11 @@ */ #include "internal.h" +#include "metal/utils.h" #include "yadif.h" -#include -#include -#include -#include +#include "libavutil/avassert.h" +#include "libavutil/hwcontext.h" +#include "libavutil/objc.h" extern char ff_vf_yadif_videotoolbox_metallib_data[]; extern unsigned int ff_vf_yadif_videotoolbox_metallib_len; From 376790086046f57283491854544ea85cfd73e4ce Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 21 Dec 2021 02:34:51 -0600 Subject: [PATCH 599/894] configure: ensure we use the macOS SDK's metal compiler by default Apparently on some OS and Xcode versions this can select an iOS SDK, which in turn may fail on the affected versions. --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index df7f5df4d9..93c1fb1871 100755 --- a/configure +++ b/configure @@ -3844,8 +3844,8 @@ host_cc_default="gcc" doxygen_default="doxygen" install="install" ln_s_default="ln -s -f" -metalcc_default="xcrun metal" -metallib_default="xcrun metallib" +metalcc_default="xcrun -sdk macosx metal" +metallib_default="xcrun -sdk macosx metallib" nm_default="nm -g" pkg_config_default=pkg-config ranlib_default="ranlib" From 62ad427823a22e2afa5069f9611ce07d6a87da78 Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 21 Dec 2021 02:35:40 -0600 Subject: [PATCH 600/894] configure: test the metal compiler before use Apparently Metal.framework is included with the command line tools (and thus may be present without Xcode), but the Metal compiler is only included as part of Xcode. --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 93c1fb1871..410f7cb241 100755 --- a/configure +++ b/configure @@ -6365,6 +6365,8 @@ enabled videotoolbox && { check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_428_1 "-framework CoreVideo" } +enabled metal && test_cmd $metalcc -v || disable metal + check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss check_type "windows.h dxva.h" "DXVA_PicParams_AV1" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 From 0f77ee9d97a9a9ed56da59a192acc616f574b932 Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 21 Dec 2021 02:37:10 -0600 Subject: [PATCH 601/894] lavfi/metal: fix build on pre-10.15 SDKs --- libavfilter/metal/utils.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m index f831502065..f365d3ceea 100644 --- a/libavfilter/metal/utils.m +++ b/libavfilter/metal/utils.m @@ -29,6 +29,8 @@ void ff_metal_compute_encoder_dispatch(id device, NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); BOOL fallback = YES; + // MAC_OS_X_VERSION_10_15 is only defined on SDKs new enough to include its functionality (including iOS, tvOS, etc) +#ifdef MAC_OS_X_VERSION_10_15 if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { if ([device supportsFamily:MTLGPUFamilyCommon3]) { MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); @@ -36,6 +38,7 @@ void ff_metal_compute_encoder_dispatch(id device, fallback = NO; } } +#endif if (fallback) { MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, (height + h - 1) / h, From 8e24a8e93a9e0326967cf61a5caa243f566b3f81 Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 21 Dec 2021 02:38:18 -0600 Subject: [PATCH 602/894] lavfi/metal: fix build with pre-10.11 deployment targets - Ensure the yadif .metal compiles when targeting any Metal runtime version - Use some preprocessor awkwardness to ensure Core Video's Metal-specific functionality is exposed regardless of our deployment target (this works around what seems to be an SDK header bug, filed as FB9816002) - Ensure all direct references to Metal functions and classes are gated behind runtime version checks (this satisfies clang's deployment-target violation warnings provided by -Wunguarded-availability). --- libavfilter/metal/utils.h | 28 +++++++- libavfilter/metal/vf_yadif_videotoolbox.metal | 11 ++- libavfilter/vf_yadif_videotoolbox.m | 67 ++++++++++++++++--- 3 files changed, 94 insertions(+), 12 deletions(-) diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h index bd0319f63c..7350d42a35 100644 --- a/libavfilter/metal/utils.h +++ b/libavfilter/metal/utils.h @@ -20,16 +20,40 @@ #define AVFILTER_METAL_UTILS_H #include + +#include + +// CoreVideo accidentally(?) preprocessor-gates Metal functionality +// on MAC_OS_X_VERSION_MIN_REQUIRED >= 101100 (FB9816002). +// There doesn't seem to be any particular reason for this, +// so here we temporarily redefine it to at least that value +// so CV will give us CVMetalTextureRef and the related functions. + +#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101100) +#define ORIG_MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_MIN_REQUIRED +#undef MAC_OS_X_VERSION_MIN_REQUIRED +#define MAC_OS_X_VERSION_MIN_REQUIRED 101100 +#endif + #include +#ifdef ORIG_MAC_OS_X_VERSION_MIN_REQUIRED +#undef MAC_OS_X_VERSION_MIN_REQUIRED +#define MAC_OS_X_VERSION_MIN_REQUIRED ORIG_MAC_OS_X_VERSION_MIN_REQUIRED +#undef ORIG_MAC_OS_X_VERSION_MIN_REQUIRED +#endif + void ff_metal_compute_encoder_dispatch(id device, id pipeline, id encoder, - NSUInteger width, NSUInteger height); + NSUInteger width, NSUInteger height) + API_AVAILABLE(macos(10.11), ios(8.0)); CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, CVMetalTextureCacheRef textureCache, CVPixelBufferRef pixbuf, int plane, - MTLPixelFormat format); + MTLPixelFormat format) + API_AVAILABLE(macos(10.11), ios(8.0)); + #endif /* AVFILTER_METAL_UTILS_H */ diff --git a/libavfilter/metal/vf_yadif_videotoolbox.metal b/libavfilter/metal/vf_yadif_videotoolbox.metal index 50783f2ffe..8a3d41a30f 100644 --- a/libavfilter/metal/vf_yadif_videotoolbox.metal +++ b/libavfilter/metal/vf_yadif_videotoolbox.metal @@ -26,6 +26,15 @@ using namespace metal; +/* + * Version compat shims + */ + +#if __METAL_VERSION__ < 210 +#define max3(x, y, z) max(x, max(y, z)) +#define min3(x, y, z) min(x, min(y, z)) +#endif + /* * Parameters */ @@ -44,7 +53,7 @@ struct deintParams { */ #define accesstype access::sample -const sampler s(coord::pixel); +constexpr sampler s(coord::pixel); template T tex2D(texture2d tex, uint x, uint y) diff --git a/libavfilter/vf_yadif_videotoolbox.m b/libavfilter/vf_yadif_videotoolbox.m index 65f155982e..455745817f 100644 --- a/libavfilter/vf_yadif_videotoolbox.m +++ b/libavfilter/vf_yadif_videotoolbox.m @@ -26,10 +26,12 @@ #include "libavutil/hwcontext.h" #include "libavutil/objc.h" +#include + extern char ff_vf_yadif_videotoolbox_metallib_data[]; extern unsigned int ff_vf_yadif_videotoolbox_metallib_len; -typedef struct YADIFVTContext { +typedef struct API_AVAILABLE(macos(10.11), ios(8.0)) YADIFVTContext { YADIFContext yadif; AVBufferRef *device_ref; @@ -44,7 +46,12 @@ typedef struct YADIFVTContext { id mtlParamsBuffer; CVMetalTextureCacheRef textureCache; -} YADIFVTContext; +} YADIFVTContext API_AVAILABLE(macos(10.11), ios(8.0)); + +// Using sizeof(YADIFVTContext) outside of an availability check will error +// if we're targeting an older OS version, so we need to calculate the size ourselves +// (we'll statically verify it's correct in yadif_videotoolbox_init behind a check) +#define YADIF_VT_CTX_SIZE (sizeof(YADIFContext) + sizeof(void*) * 10) struct mtlYadifParams { uint channels; @@ -62,7 +69,7 @@ static void call_kernel(AVFilterContext *ctx, id next, int channels, int parity, - int tff) + int tff) API_AVAILABLE(macos(10.11), ios(8.0)) { YADIFVTContext *s = ctx->priv; id buffer = s->mtlQueue.commandBuffer; @@ -93,7 +100,7 @@ static void call_kernel(AVFilterContext *ctx, } static void filter(AVFilterContext *ctx, AVFrame *dst, - int parity, int tff) + int parity, int tff) API_AVAILABLE(macos(10.11), ios(8.0)) { YADIFVTContext *s = ctx->priv; YADIFContext *y = &s->yadif; @@ -162,7 +169,7 @@ exit: return; } -static av_cold void yadif_videotoolbox_uninit(AVFilterContext *ctx) +static av_cold void do_uninit(AVFilterContext *ctx) API_AVAILABLE(macos(10.11), ios(8.0)) { YADIFVTContext *s = ctx->priv; YADIFContext *y = &s->yadif; @@ -188,7 +195,15 @@ static av_cold void yadif_videotoolbox_uninit(AVFilterContext *ctx) } } -static av_cold int yadif_videotoolbox_init(AVFilterContext *ctx) + +static av_cold void yadif_videotoolbox_uninit(AVFilterContext *ctx) +{ + if (@available(macOS 10.11, iOS 8.0, *)) { + do_uninit(ctx); + } +} + +static av_cold int do_init(AVFilterContext *ctx) API_AVAILABLE(macos(10.11), ios(8.0)) { YADIFVTContext *s = ctx->priv; NSError *err = nil; @@ -261,7 +276,19 @@ fail: return AVERROR_EXTERNAL; } -static int config_input(AVFilterLink *inlink) +static av_cold int yadif_videotoolbox_init(AVFilterContext *ctx) +{ + if (@available(macOS 10.11, iOS 8.0, *)) { + // Ensure we calculated YADIF_VT_CTX_SIZE correctly + static_assert(YADIF_VT_CTX_SIZE == sizeof(YADIFVTContext), "Incorrect YADIF_VT_CTX_SIZE value!"); + return do_init(ctx); + } else { + av_log(ctx, AV_LOG_ERROR, "Metal is not available on this OS version\n"); + return AVERROR(ENOSYS); + } +} + +static int do_config_input(AVFilterLink *inlink) API_AVAILABLE(macos(10.11), ios(8.0)) { AVFilterContext *ctx = inlink->dst; YADIFVTContext *s = ctx->priv; @@ -283,7 +310,18 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int config_output(AVFilterLink *link) +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + if (@available(macOS 10.11, iOS 8.0, *)) { + return do_config_input(inlink); + } else { + av_log(ctx, AV_LOG_ERROR, "Metal is not available on this OS version\n"); + return AVERROR(ENOSYS); + } +} + +static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(8.0)) { AVHWFramesContext *output_frames; AVFilterContext *ctx = link->src; @@ -347,6 +385,17 @@ exit: return ret; } +static int config_output(AVFilterLink *link) +{ + AVFilterContext *ctx = link->src; + if (@available(macOS 10.11, iOS 8.0, *)) { + return do_config_output(link); + } else { + av_log(ctx, AV_LOG_ERROR, "Metal is not available on this OS version\n"); + return AVERROR(ENOSYS); + } +} + #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit } @@ -394,7 +443,7 @@ static const AVFilterPad yadif_videotoolbox_outputs[] = { AVFilter ff_vf_yadif_videotoolbox = { .name = "yadif_videotoolbox", .description = NULL_IF_CONFIG_SMALL("YADIF for VideoToolbox frames using Metal compute"), - .priv_size = sizeof(YADIFVTContext), + .priv_size = YADIF_VT_CTX_SIZE, .priv_class = &yadif_videotoolbox_class, .init = yadif_videotoolbox_init, .uninit = yadif_videotoolbox_uninit, From ba44843f405d69ba51332b05a1eb959e93343567 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Wed, 22 Dec 2021 16:26:02 +0800 Subject: [PATCH 603/894] MAINTAINERS: add my gpg fingerprint Signed-off-by: Haihao Xiang --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 50ee5efecc..c065e94498 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -611,6 +611,7 @@ Daniel Verkamp 78A6 07ED 782C 653E C628 B8B9 F0EB 8DD8 2F0E 21C7 FFmpeg release signing key FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8 Ganesh Ajjanagadde C96A 848E 97C3 CEA2 AB72 5CE4 45F9 6A2D 3C36 FB1B Gwenole Beauchesne 2E63 B3A6 3E44 37E2 017D 2704 53C7 6266 B153 99C4 +Haihao Xiang (haihao) 1F0C 31E8 B4FE F7A4 4DC1 DC99 E0F5 76D4 76FC 437F Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368 James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0 Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A From 3e00b9e395fd6bc1d79e0e30885b7ccc2c9ecbba Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 01:33:00 -0600 Subject: [PATCH 604/894] swscale/x86/init: use isSemiPlanarYUV Fixes P210/P410 cases introduced (and broken) in 88d804b7ffa20caab2e8e2809da974c41f7fd8fc --- libswscale/x86/swscale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index ffc7691c12..fdc93866a6 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -417,14 +417,14 @@ av_cold void ff_sws_init_swscale_x86(SwsContext *c) #define ASSIGN_VSCALEX_FUNC(vscalefn, opt, do_16_case, condition_8bit) \ switch(c->dstBpc){ \ case 16: do_16_case; break; \ - case 10: if (!isBE(c->dstFormat) && c->dstFormat != AV_PIX_FMT_P010LE) vscalefn = ff_yuv2planeX_10_ ## opt; break; \ + case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \ case 9: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2planeX_9_ ## opt; break; \ case 8: if ((condition_8bit) && !c->use_mmx_vfilter) vscalefn = ff_yuv2planeX_8_ ## opt; break; \ } #define ASSIGN_VSCALE_FUNC(vscalefn, opt1, opt2, opt2chk) \ switch(c->dstBpc){ \ case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt1; break; \ - case 10: if (!isBE(c->dstFormat) && c->dstFormat != AV_PIX_FMT_P010LE && opt2chk) vscalefn = ff_yuv2plane1_10_ ## opt2; break; \ + case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat) && opt2chk) vscalefn = ff_yuv2plane1_10_ ## opt2; break; \ case 9: if (!isBE(c->dstFormat) && opt2chk) vscalefn = ff_yuv2plane1_9_ ## opt2; break; \ case 8: vscalefn = ff_yuv2plane1_8_ ## opt1; break; \ default: av_assert0(c->dstBpc>8); \ From 0598b38e9316391c76da24cc0f8c11d5e0292ae7 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Tue, 21 Dec 2021 23:18:06 +0800 Subject: [PATCH 605/894] lavc/qsvenc: specify codec name when print profile It is more clear and easily to detect the issues similar to commit 3857ecbe70e81cb6ad7a7f155c311e8522b93b3e Signed-off-by: Zhong Li Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 92a8b49fe3..be5a541409 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -47,41 +47,41 @@ struct profile_names { }; static const struct profile_names avc_profiles[] = { - { MFX_PROFILE_AVC_BASELINE, "baseline" }, - { MFX_PROFILE_AVC_MAIN, "main" }, - { MFX_PROFILE_AVC_EXTENDED, "extended" }, - { MFX_PROFILE_AVC_HIGH, "high" }, + { MFX_PROFILE_AVC_BASELINE, "avc baseline" }, + { MFX_PROFILE_AVC_MAIN, "avc main" }, + { MFX_PROFILE_AVC_EXTENDED, "avc extended" }, + { MFX_PROFILE_AVC_HIGH, "avc high" }, #if QSV_VERSION_ATLEAST(1, 15) - { MFX_PROFILE_AVC_HIGH_422, "high 422" }, + { MFX_PROFILE_AVC_HIGH_422, "avc high 422" }, #endif #if QSV_VERSION_ATLEAST(1, 4) - { MFX_PROFILE_AVC_CONSTRAINED_BASELINE, "constrained baseline" }, - { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "constrained high" }, - { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "progressive high" }, + { MFX_PROFILE_AVC_CONSTRAINED_BASELINE, "avc constrained baseline" }, + { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "avc constrained high" }, + { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "avc progressive high" }, #endif }; static const struct profile_names mpeg2_profiles[] = { - { MFX_PROFILE_MPEG2_SIMPLE, "simple" }, - { MFX_PROFILE_MPEG2_MAIN, "main" }, - { MFX_PROFILE_MPEG2_HIGH, "high" }, + { MFX_PROFILE_MPEG2_SIMPLE, "mpeg2 simple" }, + { MFX_PROFILE_MPEG2_MAIN, "mpeg2 main" }, + { MFX_PROFILE_MPEG2_HIGH, "mpeg2 high" }, }; static const struct profile_names hevc_profiles[] = { #if QSV_VERSION_ATLEAST(1, 8) - { MFX_PROFILE_HEVC_MAIN, "main" }, - { MFX_PROFILE_HEVC_MAIN10, "main10" }, - { MFX_PROFILE_HEVC_MAINSP, "mainsp" }, - { MFX_PROFILE_HEVC_REXT, "rext" }, + { MFX_PROFILE_HEVC_MAIN, "hevc main" }, + { MFX_PROFILE_HEVC_MAIN10, "hevc main10" }, + { MFX_PROFILE_HEVC_MAINSP, "hevc mainsp" }, + { MFX_PROFILE_HEVC_REXT, "hevc rext" }, #endif }; static const struct profile_names vp9_profiles[] = { #if QSV_VERSION_ATLEAST(1, 19) - { MFX_PROFILE_VP9_0, "0" }, - { MFX_PROFILE_VP9_1, "1" }, - { MFX_PROFILE_VP9_2, "2" }, - { MFX_PROFILE_VP9_3, "3" }, + { MFX_PROFILE_VP9_0, "vp9 0" }, + { MFX_PROFILE_VP9_1, "vp9 1" }, + { MFX_PROFILE_VP9_2, "vp9 2" }, + { MFX_PROFILE_VP9_3, "vp9 3" }, #endif }; From 7e4747ec504586658bf12a38c304659fa8d84a6a Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Tue, 21 Dec 2021 23:22:25 +0800 Subject: [PATCH 606/894] lavc/qsvenc: enable lookahead for hevc encoding Update version based on the patch: https://patchwork.ffmpeg.org/project/ffmpeg/patch/20211009015949.1510-1-haihao.xiang@intel.com/ Signed-off-by: Daniel Socek Signed-off-by: Haihao Xiang Signed-off-by: Zhong Li --- libavcodec/qsvenc.c | 10 ++++++++++ libavcodec/qsvenc_hevc.c | 3 +++ 2 files changed, 13 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index be5a541409..db6d397068 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -210,6 +210,11 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier); +#if QSV_HAVE_LA + if (info->RateControlMethod == MFX_RATECONTROL_VBR && q->extbrc && q->look_ahead_depth > 0 ) { + av_log(avctx, AV_LOG_VERBOSE, "LookAheadDepth: %"PRIu16"\n",co2->LookAheadDepth); + } +#endif } else if (info->RateControlMethod == MFX_RATECONTROL_CQP) { av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", info->QPI, info->QPP, info->QPB); @@ -742,6 +747,11 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) switch (q->param.mfx.RateControlMethod) { case MFX_RATECONTROL_CBR: case MFX_RATECONTROL_VBR: +#if QSV_HAVE_LA + if (q->extbrc) { + q->extco2.LookAheadDepth = q->look_ahead_depth; + } +#endif #if QSV_HAVE_VCM case MFX_RATECONTROL_VCM: #endif diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index b7b2f5633e..5847ea21f7 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -235,6 +235,9 @@ static const AVOption options[] = { { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session", OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VE }, +#if QSV_HAVE_LA + { "look_ahead_depth", "Depth of look ahead in number frames, available when extbrc option is enabled", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE }, +#endif { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, From ed6c5c13b10930ea95c622d6ef6e32a6e2077018 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Thu, 23 Dec 2021 10:26:37 +0800 Subject: [PATCH 607/894] libavutil/hwcontext_qsv: clean padding when upload qsv frames Fix #7830 When we upload a frame that is not padded as MSDK requires, we create a new AVFrame to copy data. The frame's padding data is uninitialized so it brings run to run problem. For example, If we run the following command serveral times we will get different outputs. ffmpeg -init_hw_device qsv=qsv:hw -qsv_device /dev/dri/renderD128 \ -filter_hw_device qsv -f rawvideo -s 192x200 -pix_fmt p010 \ -i 192x200_P010.yuv -vf "format=nv12,hwupload=extra_hw_frames=16" \ -c:v hevc_qsv output.265 According to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#encoding-procedures "Note: It is the application's responsibility to fill pixels outside of crop window when it is smaller than frame to be encoded. Especially in cases when crops are not aligned to minimum coding block size (16 for AVC, 8 for HEVC and VP9)" I add a function to fill padding area with border pixel to fix this run2run problem, and also move the new AVFrame to global structure to reduce redundant allocation operation to increase preformance. Signed-off-by: Wenbin Chen Signed-off-by: Haihao Xiang --- libavutil/hwcontext_qsv.c | 96 +++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 13 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index a5d154a24d..853fb7f60d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -47,6 +47,7 @@ #include "pixfmt.h" #include "pixdesc.h" #include "time.h" +#include "imgutils.h" #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ (MFX_VERSION_MAJOR > (MAJOR) || \ @@ -90,6 +91,7 @@ typedef struct QSVFramesContext { mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxExtBuffer *ext_buffers[1]; + AVFrame realigned_tmp_frame; } QSVFramesContext; static const struct { @@ -137,6 +139,54 @@ static uint32_t qsv_get_d3d11va_bind_flags(int mem_type) } #endif +static int qsv_fill_border(AVFrame *dst, const AVFrame *src) +{ + const AVPixFmtDescriptor *desc; + int i, planes_nb = 0; + if (dst->format != src->format) + return AVERROR(EINVAL); + + desc = av_pix_fmt_desc_get(dst->format); + + for (i = 0; i < desc->nb_components; i++) + planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); + + for (i = 0; i < planes_nb; i++) { + int sheight, dheight, y; + ptrdiff_t swidth = av_image_get_linesize(src->format, + src->width, + i); + ptrdiff_t dwidth = av_image_get_linesize(dst->format, + dst->width, + i); + const AVComponentDescriptor comp = desc->comp[i]; + if (swidth < 0 || dwidth < 0) { + av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); + return AVERROR(EINVAL); + } + sheight = src->height; + dheight = dst->height; + if (i) { + sheight = AV_CEIL_RSHIFT(src->height, desc->log2_chroma_h); + dheight = AV_CEIL_RSHIFT(dst->height, desc->log2_chroma_h); + } + //fill right padding + for (y = 0; y < sheight; y++) { + void *line_ptr = dst->data[i] + y*dst->linesize[i] + swidth; + av_memcpy_backptr(line_ptr, + comp.depth > 8 ? 2 : 1, + dwidth - swidth); + } + //fill bottom padding + for (y = sheight; y < dheight; y++) { + memcpy(dst->data[i]+y*dst->linesize[i], + dst->data[i]+(sheight-1)*dst->linesize[i], + dwidth); + } + } + return 0; +} + static int qsv_device_init(AVHWDeviceContext *ctx) { AVQSVDeviceContext *hwctx = ctx->hwctx; @@ -220,6 +270,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) av_freep(&s->surface_ptrs); av_freep(&s->surfaces_internal); av_freep(&s->handle_pairs_internal); + av_frame_unref(&s->realigned_tmp_frame); av_buffer_unref(&s->child_frames_ref); } @@ -1014,12 +1065,13 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, QSVFramesContext *s = ctx->internal->priv; mfxFrameSurface1 in = {{ 0 }}; mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; + mfxFrameInfo tmp_info; mfxSyncPoint sync = NULL; mfxStatus err; int ret = 0; /* make a copy if the input is not padded as libmfx requires */ - AVFrame tmp_frame; + AVFrame *tmp_frame = &s->realigned_tmp_frame; const AVFrame *src_frame; int realigned = 0; @@ -1048,24 +1100,40 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, if (ret < 0) return ret; + /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16. + * Height must be a multiple of 16 for progressive frame sequence and a + * multiple of 32 otherwise.", so allign all frames to 16 before uploading. */ if (src->height & 15 || src->linesize[0] & 15) { realigned = 1; - memset(&tmp_frame, 0, sizeof(tmp_frame)); - tmp_frame.format = src->format; - tmp_frame.width = FFALIGN(src->width, 16); - tmp_frame.height = FFALIGN(src->height, 16); - ret = av_frame_get_buffer(&tmp_frame, 0); - if (ret < 0) - return ret; + if (tmp_frame->format != src->format || + tmp_frame->width != FFALIGN(src->width, 16) || + tmp_frame->height != FFALIGN(src->height, 16)) { + av_frame_unref(tmp_frame); - ret = av_frame_copy(&tmp_frame, src); + tmp_frame->format = src->format; + tmp_frame->width = FFALIGN(src->width, 16); + tmp_frame->height = FFALIGN(src->height, 16); + ret = av_frame_get_buffer(tmp_frame, 0); + if (ret < 0) + return ret; + } + ret = av_frame_copy(tmp_frame, src); if (ret < 0) { - av_frame_unref(&tmp_frame); + av_frame_unref(tmp_frame); return ret; } + ret = qsv_fill_border(tmp_frame, src); + if (ret < 0) { + av_frame_unref(tmp_frame); + return ret; + } + + tmp_info = out->Info; + out->Info.CropW = FFMIN(out->Info.Width, tmp_frame->width); + out->Info.CropH = FFMIN(out->Info.Height, tmp_frame->height); } - src_frame = realigned ? &tmp_frame : src; + src_frame = realigned ? tmp_frame : src; if (!s->session_upload) { if (s->child_frames_ref) @@ -1097,8 +1165,10 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, return AVERROR_UNKNOWN; } - if (realigned) - av_frame_unref(&tmp_frame); + if (realigned) { + out->Info.CropW = tmp_info.CropW; + out->Info.CropH = tmp_info.CropH; + } return 0; } From 72bcbe216ef3d47498392ed2bada83994cd9fc86 Mon Sep 17 00:00:00 2001 From: yuanhecai Date: Sat, 18 Dec 2021 22:27:54 +0800 Subject: [PATCH 608/894] avcodec: [loongarch] Optimize vp8_lpf/mc with LSX. ./ffmpeg -i ../9_vp8_1080p_30fps_2Mbps.webm -f rawvideo -y /dev/null -an before: 210fps after : 585fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 3 + libavcodec/loongarch/vp8_lpf_lsx.c | 591 ++++++++++++ libavcodec/loongarch/vp8_mc_lsx.c | 951 +++++++++++++++++++ libavcodec/loongarch/vp8dsp_init_loongarch.c | 63 ++ libavcodec/loongarch/vp8dsp_loongarch.h | 90 ++ libavcodec/vp8dsp.c | 2 + libavcodec/vp8dsp.h | 1 + 7 files changed, 1701 insertions(+) create mode 100644 libavcodec/loongarch/vp8_lpf_lsx.c create mode 100644 libavcodec/loongarch/vp8_mc_lsx.c create mode 100644 libavcodec/loongarch/vp8dsp_init_loongarch.c create mode 100644 libavcodec/loongarch/vp8dsp_loongarch.h diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 30799e4e48..4e1d827e19 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -2,9 +2,12 @@ OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_init_loongarch.o OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch.o +OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ loongarch/h264idct_lasx.o \ loongarch/h264_deblock_lasx.o LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o +LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ + loongarch/vp8_lpf_lsx.o diff --git a/libavcodec/loongarch/vp8_lpf_lsx.c b/libavcodec/loongarch/vp8_lpf_lsx.c new file mode 100644 index 0000000000..f0fc3f3a5b --- /dev/null +++ b/libavcodec/loongarch/vp8_lpf_lsx.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/vp8dsp.h" +#include "vp8dsp_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +#define VP8_LPF_FILTER4_4W(p1_in_out, p0_in_out, q0_in_out, q1_in_out, \ + mask_in, hev_in) \ +{ \ + __m128i p1_m, p0_m, q0_m, q1_m, q0_sub_p0, filt_sign; \ + __m128i filt, filt1, filt2, cnst4b, cnst3b; \ + __m128i q0_sub_p0_l, q0_sub_p0_h, filt_h, filt_l, cnst3h; \ + \ + p1_m = __lsx_vxori_b(p1_in_out, 0x80); \ + p0_m = __lsx_vxori_b(p0_in_out, 0x80); \ + q0_m = __lsx_vxori_b(q0_in_out, 0x80); \ + q1_m = __lsx_vxori_b(q1_in_out, 0x80); \ + filt = __lsx_vssub_b(p1_m, q1_m); \ + filt = filt & hev_in; \ + \ + q0_sub_p0 = __lsx_vsub_b(q0_m, p0_m); \ + filt_sign = __lsx_vslti_b(filt, 0); \ + \ + cnst3h = __lsx_vreplgr2vr_h(3); \ + q0_sub_p0_l = __lsx_vilvl_b(q0_sub_p0, q0_sub_p0); \ + q0_sub_p0_l = __lsx_vdp2_h_b(q0_sub_p0_l, cnst3h); \ + filt_l = __lsx_vilvl_b(filt_sign, filt); \ + filt_l = __lsx_vadd_h(filt_l, q0_sub_p0_l); \ + filt_l = __lsx_vsat_h(filt_l, 7); \ + \ + q0_sub_p0_h = __lsx_vilvh_b(q0_sub_p0, q0_sub_p0); \ + q0_sub_p0_h = __lsx_vdp2_h_b(q0_sub_p0_h, cnst3h); \ + filt_h = __lsx_vilvh_b(filt_sign, filt); \ + filt_h = __lsx_vadd_h(filt_h, q0_sub_p0_h); \ + filt_h = __lsx_vsat_h(filt_h, 7); \ + \ + filt = __lsx_vpickev_b(filt_h, filt_l); \ + filt = filt & mask_in; \ + cnst4b = __lsx_vreplgr2vr_b(4); \ + filt1 = __lsx_vsadd_b(filt, cnst4b); \ + filt1 = __lsx_vsrai_b(filt1, 3); \ + \ + cnst3b = __lsx_vreplgr2vr_b(3); \ + filt2 = __lsx_vsadd_b(filt, cnst3b); \ + filt2 = __lsx_vsrai_b(filt2, 3); \ + \ + q0_m = __lsx_vssub_b(q0_m, filt1); \ + q0_in_out = __lsx_vxori_b(q0_m, 0x80); \ + p0_m = __lsx_vsadd_b(p0_m, filt2); \ + p0_in_out = __lsx_vxori_b(p0_m, 0x80); \ + \ + filt = __lsx_vsrari_b(filt1, 1); \ + hev_in = __lsx_vxori_b(hev_in, 0xff); \ + filt = filt & hev_in; \ + \ + q1_m = __lsx_vssub_b(q1_m, filt); \ + q1_in_out = __lsx_vxori_b(q1_m, 0x80); \ + p1_m = __lsx_vsadd_b(p1_m, filt); \ + p1_in_out = __lsx_vxori_b(p1_m, 0x80); \ +} + +#define VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) \ +{ \ + __m128i p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \ + __m128i filt, q0_sub_p0, cnst4b, cnst3b; \ + __m128i u, filt1, filt2, filt_sign, q0_sub_p0_sign; \ + __m128i q0_sub_p0_l, q0_sub_p0_h, filt_l, u_l, u_h, filt_h; \ + __m128i cnst3h, cnst27h, cnst18h, cnst63h; \ + \ + cnst3h = __lsx_vreplgr2vr_h(3); \ + \ + p2_m = __lsx_vxori_b(p2, 0x80); \ + p1_m = __lsx_vxori_b(p1, 0x80); \ + p0_m = __lsx_vxori_b(p0, 0x80); \ + q0_m = __lsx_vxori_b(q0, 0x80); \ + q1_m = __lsx_vxori_b(q1, 0x80); \ + q2_m = __lsx_vxori_b(q2, 0x80); \ + \ + filt = __lsx_vssub_b(p1_m, q1_m); \ + q0_sub_p0 = __lsx_vsub_b(q0_m, p0_m); \ + q0_sub_p0_sign = __lsx_vslti_b(q0_sub_p0, 0); \ + filt_sign = __lsx_vslti_b(filt, 0); \ + \ + /* right part */ \ + q0_sub_p0_l = __lsx_vilvl_b(q0_sub_p0_sign, q0_sub_p0); \ + q0_sub_p0_l = __lsx_vmul_h(q0_sub_p0_l, cnst3h); \ + filt_l = __lsx_vilvl_b(filt_sign, filt); \ + filt_l = __lsx_vadd_h(filt_l, q0_sub_p0_l); \ + filt_l = __lsx_vsat_h(filt_l, 7); \ + \ + /* left part */ \ + q0_sub_p0_h = __lsx_vilvh_b(q0_sub_p0_sign, q0_sub_p0); \ + q0_sub_p0_h = __lsx_vmul_h(q0_sub_p0_h, cnst3h); \ + filt_h = __lsx_vilvh_b(filt_sign, filt); \ + filt_h = __lsx_vadd_h(filt_h, q0_sub_p0_h); \ + filt_h = __lsx_vsat_h(filt_h, 7); \ + \ + /* combine left and right part */ \ + filt = __lsx_vpickev_b(filt_h, filt_l); \ + filt = filt & mask; \ + filt2 = filt & hev; \ + /* filt_val &= ~hev */ \ + hev = __lsx_vxori_b(hev, 0xff); \ + filt = filt & hev; \ + cnst4b = __lsx_vreplgr2vr_b(4); \ + filt1 = __lsx_vsadd_b(filt2, cnst4b); \ + filt1 = __lsx_vsrai_b(filt1, 3); \ + cnst3b = __lsx_vreplgr2vr_b(3); \ + filt2 = __lsx_vsadd_b(filt2, cnst3b); \ + filt2 = __lsx_vsrai_b(filt2, 3); \ + q0_m = __lsx_vssub_b(q0_m, filt1); \ + p0_m = __lsx_vsadd_b(p0_m, filt2); \ + \ + filt_sign = __lsx_vslti_b(filt, 0); \ + filt_l = __lsx_vilvl_b(filt_sign, filt); \ + filt_h = __lsx_vilvh_b(filt_sign, filt); \ + \ + cnst27h = __lsx_vreplgr2vr_h(27); \ + cnst63h = __lsx_vreplgr2vr_h(63); \ + \ + /* right part */ \ + u_l = __lsx_vmul_h(filt_l, cnst27h); \ + u_l = __lsx_vadd_h(u_l, cnst63h); \ + u_l = __lsx_vsrai_h(u_l, 7); \ + u_l = __lsx_vsat_h(u_l, 7); \ + /* left part */ \ + u_h = __lsx_vmul_h(filt_h, cnst27h); \ + u_h = __lsx_vadd_h(u_h, cnst63h); \ + u_h = __lsx_vsrai_h(u_h, 7); \ + u_h = __lsx_vsat_h(u_h, 7); \ + /* combine left and right part */ \ + u = __lsx_vpickev_b(u_h, u_l); \ + q0_m = __lsx_vssub_b(q0_m, u); \ + q0 = __lsx_vxori_b(q0_m, 0x80); \ + p0_m = __lsx_vsadd_b(p0_m, u); \ + p0 = __lsx_vxori_b(p0_m, 0x80); \ + cnst18h = __lsx_vreplgr2vr_h(18); \ + u_l = __lsx_vmul_h(filt_l, cnst18h); \ + u_l = __lsx_vadd_h(u_l, cnst63h); \ + u_l = __lsx_vsrai_h(u_l, 7); \ + u_l = __lsx_vsat_h(u_l, 7); \ + \ + /* left part */ \ + u_h = __lsx_vmul_h(filt_h, cnst18h); \ + u_h = __lsx_vadd_h(u_h, cnst63h); \ + u_h = __lsx_vsrai_h(u_h, 7); \ + u_h = __lsx_vsat_h(u_h, 7); \ + /* combine left and right part */ \ + u = __lsx_vpickev_b(u_h, u_l); \ + q1_m = __lsx_vssub_b(q1_m, u); \ + q1 = __lsx_vxori_b(q1_m, 0x80); \ + p1_m = __lsx_vsadd_b(p1_m, u); \ + p1 = __lsx_vxori_b(p1_m, 0x80); \ + u_l = __lsx_vslli_h(filt_l, 3); \ + u_l = __lsx_vadd_h(u_l, filt_l); \ + u_l = __lsx_vadd_h(u_l, cnst63h); \ + u_l = __lsx_vsrai_h(u_l, 7); \ + u_l = __lsx_vsat_h(u_l, 7); \ + \ + /* left part */ \ + u_h = __lsx_vslli_h(filt_h, 3); \ + u_h = __lsx_vadd_h(u_h, filt_h); \ + u_h = __lsx_vadd_h(u_h, cnst63h); \ + u_h = __lsx_vsrai_h(u_h, 7); \ + u_h = __lsx_vsat_h(u_h, 7); \ + /* combine left and right part */ \ + u = __lsx_vpickev_b(u_h, u_l); \ + q2_m = __lsx_vssub_b(q2_m, u); \ + q2 = __lsx_vxori_b(q2_m, 0x80); \ + p2_m = __lsx_vsadd_b(p2_m, u); \ + p2 = __lsx_vxori_b(p2_m, 0x80); \ +} + +#define LPF_MASK_HEV(p3_src, p2_src, p1_src, p0_src, \ + q0_src, q1_src, q2_src, q3_src, \ + limit_src, b_limit_src, thresh_src, \ + hev_dst, mask_dst, flat_dst) \ +{ \ + __m128i p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \ + __m128i p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \ + \ + /* absolute subtraction of pixel values */ \ + p3_asub_p2_m = __lsx_vabsd_bu(p3_src, p2_src); \ + p2_asub_p1_m = __lsx_vabsd_bu(p2_src, p1_src); \ + p1_asub_p0_m = __lsx_vabsd_bu(p1_src, p0_src); \ + q1_asub_q0_m = __lsx_vabsd_bu(q1_src, q0_src); \ + q2_asub_q1_m = __lsx_vabsd_bu(q2_src, q1_src); \ + q3_asub_q2_m = __lsx_vabsd_bu(q3_src, q2_src); \ + p0_asub_q0_m = __lsx_vabsd_bu(p0_src, q0_src); \ + p1_asub_q1_m = __lsx_vabsd_bu(p1_src, q1_src); \ + \ + /* calculation of hev */ \ + flat_dst = __lsx_vmax_bu(p1_asub_p0_m, q1_asub_q0_m); \ + hev_dst = __lsx_vslt_bu(thresh_src, flat_dst); \ + /* calculation of mask */ \ + p0_asub_q0_m = __lsx_vsadd_bu(p0_asub_q0_m, p0_asub_q0_m); \ + p1_asub_q1_m = __lsx_vsrli_b(p1_asub_q1_m, 1); \ + p0_asub_q0_m = __lsx_vsadd_bu(p0_asub_q0_m, p1_asub_q1_m); \ + mask_dst = __lsx_vslt_bu(b_limit_src, p0_asub_q0_m); \ + mask_dst = __lsx_vmax_bu(flat_dst, mask_dst); \ + p3_asub_p2_m = __lsx_vmax_bu(p3_asub_p2_m, p2_asub_p1_m); \ + mask_dst = __lsx_vmax_bu(p3_asub_p2_m, mask_dst); \ + q2_asub_q1_m = __lsx_vmax_bu(q2_asub_q1_m, q3_asub_q2_m); \ + mask_dst = __lsx_vmax_bu(q2_asub_q1_m, mask_dst); \ + mask_dst = __lsx_vslt_bu(limit_src, mask_dst); \ + mask_dst = __lsx_vxori_b(mask_dst, 0xff); \ +} + +#define VP8_ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) \ +{ \ + __lsx_vstelm_w(in0, pdst, 0, in0_idx); \ + __lsx_vstelm_h(in1, pdst + stride, 0, in1_idx); \ +} + +#define ST_W4(in, idx0, idx1, idx2, idx3, pdst, stride) \ +{ \ + __lsx_vstelm_w(in, pdst, 0, idx0); \ + pdst += stride; \ + __lsx_vstelm_w(in, pdst, 0, idx1); \ + pdst += stride; \ + __lsx_vstelm_w(in, pdst, 0, idx2); \ + pdst += stride; \ + __lsx_vstelm_w(in, pdst, 0, idx3); \ + pdst += stride; \ +} + +void ff_vp8_v_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + /*load vector elements*/ + DUP4_ARG2(__lsx_vld, dst - stride4, 0, dst - stride3, 0, dst - stride2, 0, + dst - stride, 0, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst + stride, 0, dst + stride2, 0, dst + stride3, 0, + q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + /*store vector elements*/ + __lsx_vst(p2, dst - stride3, 0); + __lsx_vst(p1, dst - stride2, 0); + __lsx_vst(p0, dst - stride, 0); + __lsx_vst(q0, dst, 0); + + __lsx_vst(q1, dst + stride, 0); + __lsx_vst(q2, dst + stride2, 0); +} + +void ff_vp8_v_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + __m128i p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u; + __m128i p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + DUP4_ARG2(__lsx_vld, dst_u - stride4, 0, dst_u - stride3, 0, dst_u - stride2, 0, + dst_u - stride, 0, p3_u, p2_u, p1_u, p0_u); + DUP4_ARG2(__lsx_vld, dst_u, 0, dst_u + stride, 0, dst_u + stride2, 0, + dst_u + stride3, 0, q0_u, q1_u, q2_u, q3_u); + + DUP4_ARG2(__lsx_vld, dst_v - stride4, 0, dst_v - stride3, 0, dst_v - stride2, 0, + dst_v - stride, 0, p3_v, p2_v, p1_v, p0_v); + DUP4_ARG2(__lsx_vld, dst_v, 0, dst_v + stride, 0, dst_v + stride2, 0, + dst_v + stride3, 0, q0_v, q1_v, q2_v, q3_v); + + /* rht 8 element of p3 are u pixel and left 8 element of p3 are v pixei */ + DUP4_ARG2(__lsx_vilvl_d, p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vilvl_d, q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + __lsx_vstelm_d(p2, dst_u - stride3, 0, 0); + __lsx_vstelm_d(p1, dst_u - stride2, 0, 0); + __lsx_vstelm_d(p0, dst_u - stride , 0, 0); + __lsx_vstelm_d(q0, dst_u, 0, 0); + + __lsx_vstelm_d(q1, dst_u + stride, 0, 0); + __lsx_vstelm_d(q2, dst_u + stride2, 0, 0); + + __lsx_vstelm_d(p2, dst_v - stride3, 0, 1); + __lsx_vstelm_d(p1, dst_v - stride2, 0, 1); + __lsx_vstelm_d(p0, dst_v - stride , 0, 1); + __lsx_vstelm_d(q0, dst_v, 0, 1); + + __lsx_vstelm_d(q1, dst_v + stride, 0, 1); + __lsx_vstelm_d(q2, dst_v + stride2, 0, 1); +} + +void ff_vp8_h_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + uint8_t *temp_src; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + __m128i row0, row1, row2, row3, row4, row5, row6, row7, row8; + __m128i row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + temp_src = dst - 4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row0, row1, row2, row3); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row4, row5, row6, row7); + + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row8, row9, row10, row11); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row12, row13, row14, row15); + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, + row11, row12, row13, row14, row15, p3, p2, p1, p0, q0, q1, q2, q3); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + tmp0 = __lsx_vilvl_b(p1, p2); + tmp1 = __lsx_vilvl_b(q0, p0); + + tmp3 = __lsx_vilvl_h(tmp1, tmp0); + tmp4 = __lsx_vilvh_h(tmp1, tmp0); + + tmp0 = __lsx_vilvh_b(p1, p2); + tmp1 = __lsx_vilvh_b(q0, p0); + + tmp6 = __lsx_vilvl_h(tmp1, tmp0); + tmp7 = __lsx_vilvh_h(tmp1, tmp0); + + tmp2 = __lsx_vilvl_b(q2, q1); + tmp5 = __lsx_vilvh_b(q2, q1); + + temp_src = dst - 3; + VP8_ST6x1_UB(tmp3, 0, tmp2, 0, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp3, 1, tmp2, 1, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp3, 2, tmp2, 2, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp3, 3, tmp2, 3, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 0, tmp2, 4, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 1, tmp2, 5, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 2, tmp2, 6, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 3, tmp2, 7, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 0, tmp5, 0, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 1, tmp5, 1, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 2, tmp5, 2, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 3, tmp5, 3, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 0, tmp5, 4, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 1, tmp5, 5, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 2, tmp5, 6, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 3, tmp5, 7, temp_src, 4); +} + +void ff_vp8_h_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + uint8_t *temp_src; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + __m128i row0, row1, row2, row3, row4, row5, row6, row7, row8; + __m128i row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + temp_src = dst_u - 4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row0, row1, row2, row3); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row4, row5, row6, row7); + + temp_src = dst_v - 4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row8, row9, row10, row11); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row12, row13, row14, row15); + + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + tmp0 = __lsx_vilvl_b(p1, p2); + tmp1 = __lsx_vilvl_b(q0, p0); + + tmp3 = __lsx_vilvl_h(tmp1, tmp0); + tmp4 = __lsx_vilvh_h(tmp1, tmp0); + + tmp0 = __lsx_vilvh_b(p1, p2); + tmp1 = __lsx_vilvh_b(q0, p0); + + tmp6 = __lsx_vilvl_h(tmp1, tmp0); + tmp7 = __lsx_vilvh_h(tmp1, tmp0); + + tmp2 = __lsx_vilvl_b(q2, q1); + tmp5 = __lsx_vilvh_b(q2, q1); + + dst_u -= 3; + VP8_ST6x1_UB(tmp3, 0, tmp2, 0, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp3, 1, tmp2, 1, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp3, 2, tmp2, 2, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp3, 3, tmp2, 3, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 0, tmp2, 4, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 1, tmp2, 5, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 2, tmp2, 6, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 3, tmp2, 7, dst_u, 4); + + dst_v -= 3; + VP8_ST6x1_UB(tmp6, 0, tmp5, 0, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp6, 1, tmp5, 1, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp6, 2, tmp5, 2, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp6, 3, tmp5, 3, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 0, tmp5, 4, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 1, tmp5, 5, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 2, tmp5, 6, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 3, tmp5, 7, dst_v, 4); +} + +void ff_vp8_v_loop_filter16_inner_lsx(uint8_t *src, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h) +{ + __m128i mask, hev, flat; + __m128i thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + /* load vector elements */ + src -= stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, p3, p2, p1, p0); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, q0, q1, q2, q3); + thresh = __lsx_vreplgr2vr_b(h); + b_limit = __lsx_vreplgr2vr_b(e); + limit = __lsx_vreplgr2vr_b(i); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP8_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + + __lsx_vst(p1, src - stride2, 0); + __lsx_vst(p0, src - stride, 0); + __lsx_vst(q0, src, 0); + __lsx_vst(q1, src + stride, 0); +} + +void ff_vp8_h_loop_filter16_inner_lsx(uint8_t *src, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h) +{ + __m128i mask, hev, flat; + __m128i thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + src -= 4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp0, tmp1, tmp2, tmp3); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp4, tmp5, tmp6, tmp7); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp8, tmp9, tmp10, tmp11); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp12, tmp13, tmp14, tmp15); + src -= 3 * stride4; + + LSX_TRANSPOSE16x8_B(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, + tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(h); + b_limit = __lsx_vreplgr2vr_b(e); + limit = __lsx_vreplgr2vr_b(i); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP8_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + + DUP2_ARG2(__lsx_vilvl_b, p0, p1, q1, q0, tmp0, tmp1); + tmp2 = __lsx_vilvl_h(tmp1, tmp0); + tmp3 = __lsx_vilvh_h(tmp1, tmp0); + + src += 2; + ST_W4(tmp2, 0, 1, 2, 3, src, stride); + ST_W4(tmp3, 0, 1, 2, 3, src, stride); + + DUP2_ARG2(__lsx_vilvh_b, p0, p1, q1, q0, tmp0, tmp1); + tmp2 = __lsx_vilvl_h(tmp1, tmp0); + tmp3 = __lsx_vilvh_h(tmp1, tmp0); + + ST_W4(tmp2, 0, 1, 2, 3, src, stride); + ST_W4(tmp3, 0, 1, 2, 3, src, stride); + src -= 4 * stride4; +} diff --git a/libavcodec/loongarch/vp8_mc_lsx.c b/libavcodec/loongarch/vp8_mc_lsx.c new file mode 100644 index 0000000000..80c4f87e80 --- /dev/null +++ b/libavcodec/loongarch/vp8_mc_lsx.c @@ -0,0 +1,951 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libavcodec/vp8dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp8dsp_loongarch.h" + +static const uint8_t mc_filt_mask_arr[16 * 3] = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + /* 4 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, + /* 4 width cases */ + 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 +}; + +static const int8_t subpel_filters_lsx[7][8] = { + {-6, 123, 12, -1, 0, 0, 0, 0}, + {2, -11, 108, 36, -8, 1, 0, 0}, /* New 1/4 pel 6 tap filter */ + {-9, 93, 50, -6, 0, 0, 0, 0}, + {3, -16, 77, 77, -16, 3, 0, 0}, /* New 1/2 pel 6 tap filter */ + {-6, 50, 93, -9, 0, 0, 0, 0}, + {1, -8, 36, 108, -11, 2, 0, 0}, /* New 1/4 pel 6 tap filter */ + {-1, 12, 123, -6, 0, 0, 0, 0}, +}; + +#define DPADD_SH3_SH(in0, in1, in2, coeff0, coeff1, coeff2) \ +( { \ + __m128i out0_m; \ + \ + out0_m = __lsx_vdp2_h_b(in0, coeff0); \ + out0_m = __lsx_vdp2add_h_b(out0_m, in1, coeff1); \ + out0_m = __lsx_vdp2add_h_b(out0_m, in2, coeff2); \ + \ + out0_m; \ +} ) + +#define VSHF_B3_SB(in0, in1, in2, in3, in4, in5, mask0, mask1, mask2, \ + out0, out1, out2) \ +{ \ + DUP2_ARG3(__lsx_vshuf_b, in1, in0, mask0, in3, in2, mask1, \ + out0, out1); \ + out2 = __lsx_vshuf_b(in5, in4, mask2); \ +} + +#define HORIZ_6TAP_FILT(src0, src1, mask0, mask1, mask2, \ + filt_h0, filt_h1, filt_h2) \ +( { \ + __m128i vec0_m, vec1_m, vec2_m; \ + __m128i hz_out_m; \ + \ + VSHF_B3_SB(src0, src1, src0, src1, src0, src1, mask0, mask1, mask2, \ + vec0_m, vec1_m, vec2_m); \ + hz_out_m = DPADD_SH3_SH(vec0_m, vec1_m, vec2_m, \ + filt_h0, filt_h1, filt_h2); \ + \ + hz_out_m = __lsx_vsrari_h(hz_out_m, 7); \ + hz_out_m = __lsx_vsat_h(hz_out_m, 7); \ + \ + hz_out_m; \ +} ) + +#define HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, \ + mask0, mask1, mask2, \ + filt0, filt1, filt2, \ + out0, out1, out2, out3) \ +{ \ + __m128i vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; \ + \ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, src2, src2, \ + mask0, src3, src3, mask0, vec0_m, vec1_m, vec2_m, vec3_m); \ + DUP4_ARG2(__lsx_vdp2_h_b, vec0_m, filt0, vec1_m, filt0, vec2_m, filt0, \ + vec3_m, filt0, out0, out1, out2, out3); \ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, src2, src2, \ + mask1, src3, src3, mask1, vec0_m, vec1_m, vec2_m, vec3_m); \ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, src2, src2, \ + mask2, src3, src3, mask2, vec4_m, vec5_m, vec6_m, vec7_m); \ + DUP4_ARG3(__lsx_vdp2add_h_b, out0, vec0_m, filt1, out1, vec1_m, filt1, \ + out2, vec2_m, filt1, out3, vec3_m, filt1, out0, out1, out2, out3); \ + DUP4_ARG3(__lsx_vdp2add_h_b, out0, vec4_m, filt2, out1, vec5_m, filt2, \ + out2, vec6_m, filt2, out3, vec7_m, filt2, out0, out1, out2, out3); \ +} + +#define FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1) \ +( { \ + __m128i tmp0; \ + \ + tmp0 = __lsx_vdp2_h_b(vec0, filt0); \ + tmp0 = __lsx_vdp2add_h_b(tmp0, vec1, filt1); \ + \ + tmp0; \ +} ) + +#define HORIZ_4TAP_FILT(src0, src1, mask0, mask1, filt_h0, filt_h1) \ +( { \ + __m128i vec0_m, vec1_m; \ + __m128i hz_out_m; \ + DUP2_ARG3(__lsx_vshuf_b, src1, src0, mask0, src1, src0, mask1, \ + vec0_m, vec1_m); \ + hz_out_m = FILT_4TAP_DPADD_S_H(vec0_m, vec1_m, filt_h0, filt_h1); \ + \ + hz_out_m = __lsx_vsrari_h(hz_out_m, 7); \ + hz_out_m = __lsx_vsat_h(hz_out_m, 7); \ + \ + hz_out_m; \ +} ) + +void ff_put_vp8_epel8_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[mx - 1]; + __m128i src0, src1, src2, src3, filt0, filt1, filt2; + __m128i mask0, mask1, mask2; + __m128i out0, out1, out2, out3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 2; + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src += src_stride4; + HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + filt0, filt1, filt2, out0, out1, out2, out3); + + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + for (loop_cnt = (height >> 2) - 1; loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src += src_stride4; + HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + filt0, filt1, filt2, out0, out1, out2, out3); + + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + } +} + +void ff_put_vp8_epel16_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[mx - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, filt0, filt1; + __m128i filt2, mask0, mask1, mask2; + __m128i out0, out1, out2, out3, out4, out5, out6, out7; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 2; + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, + 0, src + src_stride3, 0, src0 ,src2, src4, src6); + DUP4_ARG2(__lsx_vld, src, 8, src + src_stride, 8, src + src_stride2, + 8, src + src_stride3, 8, src1, src3, src5, src7); + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src6, 128, src7, 128, + src4, src5, src6, src7); + src += src_stride4; + + HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + filt0, filt1, filt2, out0, out1, out2, out3); + HORIZ_6TAP_8WID_4VECS_FILT(src4, src5, src6, src7, mask0, mask1, mask2, + filt0, filt1, filt2, out4, out5, out6, out7); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + dst += dst_stride; + __lsx_vst(out1, dst, 0); + dst += dst_stride; + + DUP2_ARG3(__lsx_vssrarni_b_h, out5, out4, 7, out7, out6, 7, out4, out5); + DUP2_ARG2(__lsx_vxori_b, out4, 128, out5, 128, out4, out5); + __lsx_vst(out4, dst, 0); + dst += dst_stride; + __lsx_vst(out5, dst, 0); + dst += dst_stride; + } +} + +void ff_put_vp8_epel8_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src7, src8, src9, src10; + __m128i src10_l, src32_l, src76_l, src98_l, src21_l, src43_l, src87_l; + __m128i src109_l, filt0, filt1, filt2; + __m128i out0_l, out1_l, out2_l, out3_l; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + src -= src_stride2; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + src4 = __lsx_vld(src, 0); + src += src_stride; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src2, src1, src4, + src3, src10_l, src32_l, src21_l, src43_l); + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, + 0, src + src_stride3, 0, src7, src8, src9, src10); + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, + 128, src7, src8, src9, src10); + src += src_stride4; + + DUP4_ARG2(__lsx_vilvl_b, src7, src4, src8, src7, src9, src8, src10, + src9, src76_l, src87_l, src98_l, src109_l); + + out0_l = DPADD_SH3_SH(src10_l, src32_l, src76_l, filt0, filt1, filt2); + out1_l = DPADD_SH3_SH(src21_l, src43_l, src87_l, filt0, filt1, filt2); + out2_l = DPADD_SH3_SH(src32_l, src76_l, src98_l, filt0, filt1, filt2); + out3_l = DPADD_SH3_SH(src43_l, src87_l, src109_l, filt0, filt1, filt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, out1_l, out0_l, 7, out3_l, out2_l, 7, + out0_l, out1_l); + DUP2_ARG2(__lsx_vxori_b, out0_l, 128, out1_l, 128, out0_l, out1_l); + + __lsx_vstelm_d(out0_l, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0_l, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1_l, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1_l, dst, 0, 1); + dst += dst_stride; + + src10_l = src76_l; + src32_l = src98_l; + src21_l = src87_l; + src43_l = src109_l; + src4 = src10; + } +} + +void ff_put_vp8_epel16_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i src10_l, src32_l, src54_l, src76_l, src21_l, src43_l, src65_l, src87_l; + __m128i src10_h, src32_h, src54_h, src76_h, src21_h, src43_h, src65_h, src87_h; + __m128i filt0, filt1, filt2; + __m128i tmp0, tmp1, tmp2, tmp3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP4_ARG2(__lsx_vld, src - src_stride2, 0, src - src_stride, 0, src, 0, + src + src_stride, 0, src0, src1, src2, src3); + src4 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, src0, + src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src4, src3, src2, src1, + src10_l, src32_l, src43_l, src21_l); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src4, src3, src2, src1, + src10_h, src32_h, src43_h, src21_h); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src5, src6, src7, src8); + src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src5, 128, src6, 128, src7, 128, src8, 128, + src5, src6, src7, src8); + + DUP4_ARG2(__lsx_vilvl_b, src5, src4, src6, src5, src7, src6, src8, src7, + src54_l, src65_l, src76_l, src87_l); + DUP4_ARG2(__lsx_vilvh_b, src5, src4, src6, src5, src7, src6, src8, src7, + src54_h, src65_h, src76_h, src87_h); + + tmp0 = DPADD_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + tmp1 = DPADD_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + tmp2 = DPADD_SH3_SH(src10_h, src32_h, src54_h, filt0, filt1, filt2); + tmp3 = DPADD_SH3_SH(src21_h, src43_h, src65_h, filt0, filt1, filt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + tmp0 = DPADD_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + tmp1 = DPADD_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + tmp2 = DPADD_SH3_SH(src32_h, src54_h, src76_h, filt0, filt1, filt2); + tmp3 = DPADD_SH3_SH(src43_h, src65_h, src87_h, filt0, filt1, filt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + src10_l = src54_l; + src32_l = src76_l; + src21_l = src65_l; + src43_l = src87_l; + src10_h = src54_h; + src32_h = src76_h; + src21_h = src65_h; + src43_h = src87_h; + src4 = src8; + } +} + +void ff_put_vp8_epel8_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter_horiz = subpel_filters_lsx[mx - 1]; + const int8_t *filter_vert = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt_hz0, filt_hz1, filt_hz2; + __m128i mask0, mask1, mask2, filt_vt0, filt_vt1, filt_vt2; + __m128i hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + __m128i hz_out7, hz_out8, out0, out1, out2, out3, out4, out5, out6, out7; + __m128i tmp0, tmp1, tmp2, tmp3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= (2 + src_stride2); + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filt_hz0, filt_hz1); + filt_hz2 = __lsx_vldrepl_h(filter_horiz, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + src4 = __lsx_vld(src, 0); + src += src_stride; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0 ,src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + hz_out0 = HORIZ_6TAP_FILT(src0, src0, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out1 = HORIZ_6TAP_FILT(src1, src1, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out2 = HORIZ_6TAP_FILT(src2, src2, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out3 = HORIZ_6TAP_FILT(src3, src3, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out4 = HORIZ_6TAP_FILT(src4, src4, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + + DUP2_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filt_vt0, filt_vt1); + filt_vt2 = __lsx_vldrepl_h(filter_vert, 4); + + DUP2_ARG2(__lsx_vpackev_b, hz_out1, hz_out0, hz_out3, hz_out2, out0, out1); + DUP2_ARG2(__lsx_vpackev_b, hz_out2, hz_out1, hz_out4, hz_out3, out3, out4); + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src5, src6, src7, src8); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src5, 128, src6, 128, src7, 128, src8, 128, + src5, src6, src7, src8); + + hz_out5 = HORIZ_6TAP_FILT(src5, src5, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + out2 = __lsx_vpackev_b(hz_out5, hz_out4); + tmp0 = DPADD_SH3_SH(out0, out1, out2,filt_vt0, filt_vt1, filt_vt2); + + hz_out6 = HORIZ_6TAP_FILT(src6, src6, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + out5 = __lsx_vpackev_b(hz_out6, hz_out5); + tmp1 = DPADD_SH3_SH(out3, out4, out5, filt_vt0, filt_vt1, filt_vt2); + + hz_out7 = HORIZ_6TAP_FILT(src7, src7, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + + out7 = __lsx_vpackev_b(hz_out7, hz_out6); + tmp2 = DPADD_SH3_SH(out1, out2, out7, filt_vt0, filt_vt1, filt_vt2); + + hz_out8 = HORIZ_6TAP_FILT(src8, src8, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + out6 = __lsx_vpackev_b(hz_out8, hz_out7); + tmp3 = DPADD_SH3_SH(out4, out5, out6, filt_vt0, filt_vt1, filt_vt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vstelm_d(tmp0, dst, 0, 0); + + dst += dst_stride; + __lsx_vstelm_d(tmp0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 1); + dst += dst_stride; + + hz_out4 = hz_out8; + out0 = out2; + out1 = out7; + out3 = out5; + out4 = out6; + } +} + +void ff_put_vp8_epel16_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + ff_put_vp8_epel8_h6v6_lsx(dst, dst_stride, src, src_stride, height, mx, my); + src += 8; + dst += 8; + } +} + +void ff_put_vp8_epel8_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src7, src8, src9, src10; + __m128i src10_l, src72_l, src98_l, src21_l, src87_l, src109_l, filt0, filt1; + __m128i out0, out1, out2, out3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + src -= src_stride; + + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src0, src1); + src2 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP2_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src0, src1); + src2 = __lsx_vxori_b(src2, 128); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_l, src21_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src7, src8, src9, src10); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src2, src8, src7, src9, src8, src10, src9, + src72_l, src87_l, src98_l, src109_l); + + out0 = FILT_4TAP_DPADD_S_H(src10_l, src72_l, filt0, filt1); + out1 = FILT_4TAP_DPADD_S_H(src21_l, src87_l, filt0, filt1); + out2 = FILT_4TAP_DPADD_S_H(src72_l, src98_l, filt0, filt1); + out3 = FILT_4TAP_DPADD_S_H(src87_l, src109_l, filt0, filt1); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + src10_l = src98_l; + src21_l = src109_l; + src2 = src10; + } +} + +void ff_put_vp8_epel16_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i src10_l, src32_l, src54_l, src21_l, src43_l, src65_l, src10_h; + __m128i src32_h, src54_h, src21_h, src43_h, src65_h, filt0, filt1; + __m128i tmp0, tmp1, tmp2, tmp3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + src -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src0, src1); + src2 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP2_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src0, src1); + src2 = __lsx_vxori_b(src2, 128); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_l, src21_l); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_h, src21_h); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, + 0, src + src_stride3, 0, src3, src4, src5, src6); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src3, 128, src4, 128, src5, 128, src6, 128, + src3, src4, src5, src6); + DUP4_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src5, src4, src6, + src5, src32_l, src43_l, src54_l, src65_l); + DUP4_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src5, src4, src6, + src5, src32_h, src43_h, src54_h, src65_h); + + tmp0 = FILT_4TAP_DPADD_S_H(src10_l, src32_l, filt0, filt1); + tmp1 = FILT_4TAP_DPADD_S_H(src21_l, src43_l, filt0, filt1); + tmp2 = FILT_4TAP_DPADD_S_H(src10_h, src32_h, filt0, filt1); + tmp3 = FILT_4TAP_DPADD_S_H(src21_h, src43_h, filt0, filt1); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + tmp0 = FILT_4TAP_DPADD_S_H(src32_l, src54_l, filt0, filt1); + tmp1 = FILT_4TAP_DPADD_S_H(src43_l, src65_l, filt0, filt1); + tmp2 = FILT_4TAP_DPADD_S_H(src32_h, src54_h, filt0, filt1); + tmp3 = FILT_4TAP_DPADD_S_H(src43_h, src65_h, filt0, filt1); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + src10_l = src54_l; + src21_l = src65_l; + src10_h = src54_h; + src21_h = src65_h; + src2 = src6; + } +} + +void ff_put_vp8_epel8_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter_horiz = subpel_filters_lsx[mx - 1]; + const int8_t *filter_vert = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i filt_hz0, filt_hz1, filt_hz2, mask0, mask1, mask2; + __m128i filt_vt0, filt_vt1, hz_out0, hz_out1, hz_out2, hz_out3; + __m128i tmp0, tmp1, tmp2, tmp3, vec0, vec1, vec2, vec3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= (2 + src_stride); + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filt_hz0, filt_hz1); + filt_hz2 = __lsx_vldrepl_h(filter_horiz, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src0, src1); + src2 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP2_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src0, src1); + src2 = __lsx_vxori_b(src2, 128); + hz_out0 = HORIZ_6TAP_FILT(src0, src0, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out1 = HORIZ_6TAP_FILT(src1, src1, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out2 = HORIZ_6TAP_FILT(src2, src2, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + DUP2_ARG2(__lsx_vpackev_b, hz_out1, hz_out0, hz_out2, hz_out1, vec0, vec2); + + DUP2_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filt_vt0, filt_vt1); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src3, src4, src5, src6); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src3, 128, src4, 128, src5, 128, src6, 128, + src3, src4, src5, src6); + + hz_out3 = HORIZ_6TAP_FILT(src3, src3, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + vec1 = __lsx_vpackev_b(hz_out3, hz_out2); + tmp0 = FILT_4TAP_DPADD_S_H(vec0, vec1, filt_vt0, filt_vt1); + + hz_out0 = HORIZ_6TAP_FILT(src4, src4, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + vec3 = __lsx_vpackev_b(hz_out0, hz_out3); + tmp1 = FILT_4TAP_DPADD_S_H(vec2, vec3, filt_vt0, filt_vt1); + + hz_out1 = HORIZ_6TAP_FILT(src5, src5, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + vec0 = __lsx_vpackev_b(hz_out1, hz_out0); + tmp2 = FILT_4TAP_DPADD_S_H(vec1, vec0, filt_vt0, filt_vt1); + + hz_out2 = HORIZ_6TAP_FILT(src6, src6, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + DUP2_ARG2(__lsx_vpackev_b, hz_out0, hz_out3, hz_out2, hz_out1, vec1, vec2); + tmp3 = FILT_4TAP_DPADD_S_H(vec1, vec2, filt_vt0, filt_vt1); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __lsx_vstelm_d(tmp0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 1); + dst += dst_stride; + } +} + +void ff_put_vp8_epel16_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + ff_put_vp8_epel8_h6v4_lsx(dst, dst_stride, src, src_stride, height, + mx, my); + src += 8; + dst += 8; + } +} + +void ff_put_vp8_epel8_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter_horiz = subpel_filters_lsx[mx - 1]; + const int8_t *filter_vert = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt_hz0, filt_hz1, mask0, mask1; + __m128i filt_vt0, filt_vt1, filt_vt2; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + __m128i out0, out1, out2, out3, out4, out5, out6, out7; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= (1 + src_stride2); + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filt_hz0, filt_hz1); + mask1 = __lsx_vaddi_bu(mask0, 2); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + src4 = __lsx_vld(src, 0); + src += src_stride; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + tmp0 = HORIZ_4TAP_FILT(src0, src0, mask0, mask1, filt_hz0, filt_hz1); + tmp1 = HORIZ_4TAP_FILT(src1, src1, mask0, mask1, filt_hz0, filt_hz1); + tmp2 = HORIZ_4TAP_FILT(src2, src2, mask0, mask1, filt_hz0, filt_hz1); + tmp3 = HORIZ_4TAP_FILT(src3, src3, mask0, mask1, filt_hz0, filt_hz1); + tmp4 = HORIZ_4TAP_FILT(src4, src4, mask0, mask1, filt_hz0, filt_hz1); + + DUP4_ARG2(__lsx_vpackev_b, tmp1, tmp0, tmp3, tmp2, tmp2, tmp1, + tmp4, tmp3, out0, out1, out3, out4); + + DUP2_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filt_vt0, filt_vt1); + filt_vt2 = __lsx_vldrepl_h(filter_vert, 4); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src5, src6, src7, src8); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src5, 128, src6, 128, src7, 128, src8, 128, + src5, src6, src7, src8); + + tmp5 = HORIZ_4TAP_FILT(src5, src5, mask0, mask1, filt_hz0, filt_hz1); + out2 = __lsx_vpackev_b(tmp5, tmp4); + tmp0 = DPADD_SH3_SH(out0, out1, out2, filt_vt0, filt_vt1, filt_vt2); + + tmp6 = HORIZ_4TAP_FILT(src6, src6, mask0, mask1, filt_hz0, filt_hz1); + out5 = __lsx_vpackev_b(tmp6, tmp5); + tmp1 = DPADD_SH3_SH(out3, out4, out5, filt_vt0, filt_vt1, filt_vt2); + + tmp7 = HORIZ_4TAP_FILT(src7, src7, mask0, mask1, filt_hz0, filt_hz1); + out6 = __lsx_vpackev_b(tmp7, tmp6); + tmp2 = DPADD_SH3_SH(out1, out2, out6, filt_vt0, filt_vt1, filt_vt2); + + tmp8 = HORIZ_4TAP_FILT(src8, src8, mask0, mask1, filt_hz0, filt_hz1); + out7 = __lsx_vpackev_b(tmp8, tmp7); + tmp3 = DPADD_SH3_SH(out4, out5, out7, filt_vt0, filt_vt1, filt_vt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __lsx_vstelm_d(tmp0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 1); + dst += dst_stride; + + tmp4 = tmp8; + out0 = out2; + out1 = out6; + out3 = out5; + out4 = out7; + } +} + +void ff_put_vp8_epel16_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + ff_put_vp8_epel8_h4v6_lsx(dst, dst_stride, src, src_stride, height, + mx, my); + src += 8; + dst += 8; + } +} + +void ff_put_vp8_pixels8_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t cnt; + __m128i src0, src1, src2, src3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + if (0 == height % 8) { + for (cnt = height >> 3; cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + } + } else if( 0 == height % 4) { + for (cnt = (height >> 2); cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + } + } +} + +void ff_put_vp8_pixels16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t width = 16; + int32_t cnt, loop_cnt; + uint8_t *src_tmp, *dst_tmp; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + ptrdiff_t dst_stride2 = dst_stride << 1; + ptrdiff_t dst_stride3 = dst_stride2 + dst_stride; + ptrdiff_t dst_stride4 = dst_stride2 << 1; + + if (0 == height % 8) { + for (cnt = (width >> 4); cnt--;) { + src_tmp = src; + dst_tmp = dst; + for (loop_cnt = (height >> 3); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src_tmp, 0, src_tmp + src_stride, 0, + src_tmp + src_stride2, 0, src_tmp + src_stride3, 0, + src4, src5, src6, src7); + src_tmp += src_stride4; + + __lsx_vst(src4, dst_tmp, 0); + __lsx_vst(src5, dst_tmp + dst_stride, 0); + __lsx_vst(src6, dst_tmp + dst_stride2, 0); + __lsx_vst(src7, dst_tmp + dst_stride3, 0); + dst_tmp += dst_stride4; + + DUP4_ARG2(__lsx_vld, src_tmp, 0, src_tmp + src_stride, 0, + src_tmp + src_stride2, 0, src_tmp + src_stride3, 0, + src4, src5, src6, src7); + src_tmp += src_stride4; + + __lsx_vst(src4, dst_tmp, 0); + __lsx_vst(src5, dst_tmp + dst_stride, 0); + __lsx_vst(src6, dst_tmp + dst_stride2, 0); + __lsx_vst(src7, dst_tmp + dst_stride3, 0); + dst_tmp += dst_stride4; + } + src += 16; + dst += 16; + } + } else if (0 == height % 4) { + for (cnt = (height >> 2); cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += 4 * src_stride4; + + __lsx_vst(src0, dst, 0); + __lsx_vst(src1, dst + dst_stride, 0); + __lsx_vst(src2, dst + dst_stride2, 0); + __lsx_vst(src3, dst + dst_stride3, 0); + dst += dst_stride4; + } + } +} diff --git a/libavcodec/loongarch/vp8dsp_init_loongarch.c b/libavcodec/loongarch/vp8dsp_init_loongarch.c new file mode 100644 index 0000000000..63da15b198 --- /dev/null +++ b/libavcodec/loongarch/vp8dsp_init_loongarch.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * VP8 compatible video decoder + */ + +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/vp8dsp.h" +#include "libavutil/attributes.h" +#include "vp8dsp_loongarch.h" + +#define VP8_MC_LOONGARCH_FUNC(IDX, SIZE) \ + dsp->put_vp8_epel_pixels_tab[IDX][0][2] = ff_put_vp8_epel##SIZE##_h6_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][0] = ff_put_vp8_epel##SIZE##_v4_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][2] = ff_put_vp8_epel##SIZE##_h6v4_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][0] = ff_put_vp8_epel##SIZE##_v6_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][1] = ff_put_vp8_epel##SIZE##_h4v6_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][2] = ff_put_vp8_epel##SIZE##_h6v6_lsx; + +#define VP8_MC_LOONGARCH_COPY(IDX, SIZE) \ + dsp->put_vp8_epel_pixels_tab[IDX][0][0] = ff_put_vp8_pixels##SIZE##_lsx; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][0][0] = ff_put_vp8_pixels##SIZE##_lsx; + +av_cold void ff_vp8dsp_init_loongarch(VP8DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lsx(cpu_flags)) { + VP8_MC_LOONGARCH_FUNC(0, 16); + VP8_MC_LOONGARCH_FUNC(1, 8); + + VP8_MC_LOONGARCH_COPY(0, 16); + VP8_MC_LOONGARCH_COPY(1, 8); + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_lsx; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_lsx; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_lsx; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_lsx; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_lsx; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_lsx; + } +} diff --git a/libavcodec/loongarch/vp8dsp_loongarch.h b/libavcodec/loongarch/vp8dsp_loongarch.h new file mode 100644 index 0000000000..87e9509db9 --- /dev/null +++ b/libavcodec/loongarch/vp8dsp_loongarch.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_VP8DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_VP8DSP_LOONGARCH_H + +#include "libavcodec/vp8dsp.h" + +void ff_put_vp8_pixels8_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int x, int y); +void ff_put_vp8_pixels16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int x, int y); + +void ff_put_vp8_epel16_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); + +void ff_put_vp8_epel8_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); + +void ff_put_vp8_epel8_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); + +/* loop filter */ +void ff_vp8_v_loop_filter16_inner_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h); +void ff_vp8_h_loop_filter16_inner_lsx(uint8_t *src, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h); + +void ff_vp8_v_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); +void ff_vp8_h_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); +void ff_vp8_h_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); +void ff_vp8_v_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); + +#endif // #ifndef AVCODEC_LOONGARCH_VP8DSP_LOONGARCH_H diff --git a/libavcodec/vp8dsp.c b/libavcodec/vp8dsp.c index 4ff63d0784..732a483b62 100644 --- a/libavcodec/vp8dsp.c +++ b/libavcodec/vp8dsp.c @@ -743,5 +743,7 @@ av_cold void ff_vp8dsp_init(VP8DSPContext *dsp) ff_vp8dsp_init_x86(dsp); if (ARCH_MIPS) ff_vp8dsp_init_mips(dsp); + if (ARCH_LOONGARCH) + ff_vp8dsp_init_loongarch(dsp); } #endif /* CONFIG_VP8_DECODER */ diff --git a/libavcodec/vp8dsp.h b/libavcodec/vp8dsp.h index cfe1524b0b..7c6208df39 100644 --- a/libavcodec/vp8dsp.h +++ b/libavcodec/vp8dsp.h @@ -101,6 +101,7 @@ void ff_vp8dsp_init_aarch64(VP8DSPContext *c); void ff_vp8dsp_init_arm(VP8DSPContext *c); void ff_vp8dsp_init_x86(VP8DSPContext *c); void ff_vp8dsp_init_mips(VP8DSPContext *c); +void ff_vp8dsp_init_loongarch(VP8DSPContext *c); #define IS_VP7 1 #define IS_VP8 0 From 2fd914e079645ad08a4068b46c161f4a01b5b996 Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Sat, 18 Dec 2021 22:27:55 +0800 Subject: [PATCH 609/894] avcodec: [loongarch] Optimize vp9_mc/intra with LSX. ffmpeg -i ../10_vp9_1080p_30fps_3Mbps.webm -f rawvideo -y /dev/null -an before:170fps after :294fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 3 + libavcodec/loongarch/vp9_intra_lsx.c | 653 +++++ libavcodec/loongarch/vp9_mc_lsx.c | 2480 ++++++++++++++++++ libavcodec/loongarch/vp9dsp_init_loongarch.c | 97 + libavcodec/loongarch/vp9dsp_loongarch.h | 144 + libavcodec/vp9dsp.c | 1 + libavcodec/vp9dsp.h | 1 + 7 files changed, 3379 insertions(+) create mode 100644 libavcodec/loongarch/vp9_intra_lsx.c create mode 100644 libavcodec/loongarch/vp9_mc_lsx.c create mode 100644 libavcodec/loongarch/vp9dsp_init_loongarch.c create mode 100644 libavcodec/loongarch/vp9dsp_loongarch.h diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 4e1d827e19..6fcebe40a3 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -3,6 +3,7 @@ OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch.o OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o +OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ @@ -11,3 +12,5 @@ LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ loongarch/vp8_lpf_lsx.o +LSX-OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9_mc_lsx.o \ + loongarch/vp9_intra_lsx.o diff --git a/libavcodec/loongarch/vp9_intra_lsx.c b/libavcodec/loongarch/vp9_intra_lsx.c new file mode 100644 index 0000000000..d3f32646f3 --- /dev/null +++ b/libavcodec/loongarch/vp9_intra_lsx.c @@ -0,0 +1,653 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp9dsp_loongarch.h" + +#define LSX_ST_8(_dst0, _dst1, _dst2, _dst3, _dst4, \ + _dst5, _dst6, _dst7, _dst, _stride, \ + _stride2, _stride3, _stride4) \ +{ \ + __lsx_vst(_dst0, _dst, 0); \ + __lsx_vstx(_dst1, _dst, _stride); \ + __lsx_vstx(_dst2, _dst, _stride2); \ + __lsx_vstx(_dst3, _dst, _stride3); \ + _dst += _stride4; \ + __lsx_vst(_dst4, _dst, 0); \ + __lsx_vstx(_dst5, _dst, _stride); \ + __lsx_vstx(_dst6, _dst, _stride2); \ + __lsx_vstx(_dst7, _dst, _stride3); \ +} + +#define LSX_ST_8X16(_dst0, _dst1, _dst2, _dst3, _dst4, \ + _dst5, _dst6, _dst7, _dst, _stride) \ +{ \ + __lsx_vst(_dst0, _dst, 0); \ + __lsx_vst(_dst0, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst1, _dst, 0); \ + __lsx_vst(_dst1, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst2, _dst, 0); \ + __lsx_vst(_dst2, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst3, _dst, 0); \ + __lsx_vst(_dst3, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst4, _dst, 0); \ + __lsx_vst(_dst4, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst5, _dst, 0); \ + __lsx_vst(_dst5, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst6, _dst, 0); \ + __lsx_vst(_dst6, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst7, _dst, 0); \ + __lsx_vst(_dst7, _dst, 16); \ + _dst += _stride; \ +} + +void ff_vert_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *left, + const uint8_t *src) +{ + __m128i src0; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + src0 = __lsx_vld(src, 0); + LSX_ST_8(src0, src0, src0, src0, src0, src0, src0, src0, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(src0, src0, src0, src0, src0, src0, src0, src0, dst, + dst_stride, stride2, stride3, stride4); +} + +void ff_vert_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *left, + const uint8_t *src) +{ + uint32_t row; + __m128i src0, src1; + + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + for (row = 32; row--;) { + __lsx_vst(src0, dst, 0); + __lsx_vst(src1, dst, 16); + dst += dst_stride; + } +} + +void ff_hor_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src, + const uint8_t *top) +{ + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + + src15 = __lsx_vldrepl_b(src, 0); + src14 = __lsx_vldrepl_b(src, 1); + src13 = __lsx_vldrepl_b(src, 2); + src12 = __lsx_vldrepl_b(src, 3); + src11 = __lsx_vldrepl_b(src, 4); + src10 = __lsx_vldrepl_b(src, 5); + src9 = __lsx_vldrepl_b(src, 6); + src8 = __lsx_vldrepl_b(src, 7); + src7 = __lsx_vldrepl_b(src, 8); + src6 = __lsx_vldrepl_b(src, 9); + src5 = __lsx_vldrepl_b(src, 10); + src4 = __lsx_vldrepl_b(src, 11); + src3 = __lsx_vldrepl_b(src, 12); + src2 = __lsx_vldrepl_b(src, 13); + src1 = __lsx_vldrepl_b(src, 14); + src0 = __lsx_vldrepl_b(src, 15); + LSX_ST_8(src0, src1, src2, src3, src4, src5, src6, src7, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(src8, src9, src10, src11, src12, src13, src14, src15, dst, + dst_stride, stride2, stride3, stride4); +} + +void ff_hor_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src, + const uint8_t *top) +{ + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + __m128i src16, src17, src18, src19, src20, src21, src22, src23; + __m128i src24, src25, src26, src27, src28, src29, src30, src31; + + src31 = __lsx_vldrepl_b(src, 0); + src30 = __lsx_vldrepl_b(src, 1); + src29 = __lsx_vldrepl_b(src, 2); + src28 = __lsx_vldrepl_b(src, 3); + src27 = __lsx_vldrepl_b(src, 4); + src26 = __lsx_vldrepl_b(src, 5); + src25 = __lsx_vldrepl_b(src, 6); + src24 = __lsx_vldrepl_b(src, 7); + src23 = __lsx_vldrepl_b(src, 8); + src22 = __lsx_vldrepl_b(src, 9); + src21 = __lsx_vldrepl_b(src, 10); + src20 = __lsx_vldrepl_b(src, 11); + src19 = __lsx_vldrepl_b(src, 12); + src18 = __lsx_vldrepl_b(src, 13); + src17 = __lsx_vldrepl_b(src, 14); + src16 = __lsx_vldrepl_b(src, 15); + src15 = __lsx_vldrepl_b(src, 16); + src14 = __lsx_vldrepl_b(src, 17); + src13 = __lsx_vldrepl_b(src, 18); + src12 = __lsx_vldrepl_b(src, 19); + src11 = __lsx_vldrepl_b(src, 20); + src10 = __lsx_vldrepl_b(src, 21); + src9 = __lsx_vldrepl_b(src, 22); + src8 = __lsx_vldrepl_b(src, 23); + src7 = __lsx_vldrepl_b(src, 24); + src6 = __lsx_vldrepl_b(src, 25); + src5 = __lsx_vldrepl_b(src, 26); + src4 = __lsx_vldrepl_b(src, 27); + src3 = __lsx_vldrepl_b(src, 28); + src2 = __lsx_vldrepl_b(src, 29); + src1 = __lsx_vldrepl_b(src, 30); + src0 = __lsx_vldrepl_b(src, 31); + LSX_ST_8X16(src0, src1, src2, src3, src4, src5, src6, src7, + dst, dst_stride); + LSX_ST_8X16(src8, src9, src10, src11, src12, src13, src14, src15, + dst, dst_stride); + LSX_ST_8X16(src16, src17, src18, src19, src20, src21, src22, src23, + dst, dst_stride); + LSX_ST_8X16(src24, src25, src26, src27, src28, src29, src30, src31, + dst, dst_stride); +} + +void ff_dc_4x4_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src_left, + const uint8_t *src_top) +{ + __m128i tmp0, tmp1, dst0; + + tmp0 = __lsx_vldrepl_w(src_top, 0); + tmp1 = __lsx_vldrepl_w(src_left, 0); + dst0 = __lsx_vilvl_w(tmp1, tmp0); + dst0 = __lsx_vhaddw_hu_bu(dst0, dst0); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 3); + dst0 = __lsx_vshuf4i_b(dst0, 0); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 0); +} + +#define INTRA_DC_TL_4X4(dir) \ +void ff_dc_##dir##_4x4_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, dst0; \ + \ + tmp0 = __lsx_vldrepl_w(dir, 0); \ + dst0 = __lsx_vhaddw_hu_bu(tmp0, tmp0); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 2); \ + dst0 = __lsx_vshuf4i_b(dst0, 0); \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ +} +INTRA_DC_TL_4X4(top); +INTRA_DC_TL_4X4(left); + +void ff_dc_8x8_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src_left, + const uint8_t *src_top) +{ + __m128i tmp0, tmp1, dst0; + + tmp0 = __lsx_vldrepl_d(src_top, 0); + tmp1 = __lsx_vldrepl_d(src_left, 0); + dst0 = __lsx_vilvl_d(tmp1, tmp0); + dst0 = __lsx_vhaddw_hu_bu(dst0, dst0); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 4); + dst0 = __lsx_vreplvei_b(dst0, 0); + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); +} + +#define INTRA_DC_TL_8X8(dir) \ +void ff_dc_##dir##_8x8_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, dst0; \ + \ + tmp0 = __lsx_vldrepl_d(dir, 0); \ + dst0 = __lsx_vhaddw_hu_bu(tmp0, tmp0); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 3); \ + dst0 = __lsx_vreplvei_b(dst0, 0); \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ +} + +INTRA_DC_TL_8X8(top); +INTRA_DC_TL_8X8(left); + +void ff_dc_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top) +{ + __m128i tmp0, tmp1, dst0; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + + tmp0 = __lsx_vld(src_top, 0); + tmp1 = __lsx_vld(src_left, 0); + DUP2_ARG2(__lsx_vhaddw_hu_bu, tmp0, tmp0, tmp1, tmp1, tmp0, tmp1); + dst0 = __lsx_vadd_h(tmp0, tmp1); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 5); + dst0 = __lsx_vreplvei_b(dst0, 0); + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, + dst_stride, stride2, stride3, stride4); +} + +#define INTRA_DC_TL_16X16(dir) \ +void ff_dc_##dir##_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, dst0; \ + ptrdiff_t stride2 = dst_stride << 1; \ + ptrdiff_t stride3 = stride2 + dst_stride; \ + ptrdiff_t stride4 = stride2 << 1; \ + \ + tmp0 = __lsx_vld(dir, 0); \ + dst0 = __lsx_vhaddw_hu_bu(tmp0, tmp0); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); \ + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 4); \ + dst0 = __lsx_vreplvei_b(dst0, 0); \ + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, \ + dst_stride, stride2, stride3, stride4); \ + dst += stride4; \ + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, \ + dst_stride, stride2, stride3, stride4); \ +} + +INTRA_DC_TL_16X16(top); +INTRA_DC_TL_16X16(left); + +void ff_dc_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top) +{ + __m128i tmp0, tmp1, tmp2, tmp3, dst0; + + DUP2_ARG2(__lsx_vld, src_top, 0, src_top, 16, tmp0, tmp1); + DUP2_ARG2(__lsx_vld, src_left, 0, src_left, 16, tmp2, tmp3); + DUP4_ARG2(__lsx_vhaddw_hu_bu, tmp0, tmp0, tmp1, tmp1, tmp2, tmp2, + tmp3, tmp3, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vadd_h, tmp0, tmp1, tmp2, tmp3, tmp0, tmp1); + dst0 = __lsx_vadd_h(tmp0, tmp1); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 6); + dst0 = __lsx_vreplvei_b(dst0, 0); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); +} + +#define INTRA_DC_TL_32X32(dir) \ +void ff_dc_##dir##_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, tmp1, dst0; \ + \ + DUP2_ARG2(__lsx_vld, dir, 0, dir, 16, tmp0, tmp1); \ + DUP2_ARG2(__lsx_vhaddw_hu_bu, tmp0, tmp0, tmp1, tmp1, tmp0, tmp1); \ + dst0 = __lsx_vadd_h(tmp0, tmp1); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); \ + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 5); \ + dst0 = __lsx_vreplvei_b(dst0, 0); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ +} + +INTRA_DC_TL_32X32(top); +INTRA_DC_TL_32X32(left); + +#define INTRA_PREDICT_VALDC_16X16_LSX(val) \ +void ff_dc_##val##_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, const uint8_t *top) \ +{ \ + __m128i out = __lsx_vldi(val); \ + ptrdiff_t stride2 = dst_stride << 1; \ + ptrdiff_t stride3 = stride2 + dst_stride; \ + ptrdiff_t stride4 = stride2 << 1; \ + \ + LSX_ST_8(out, out, out, out, out, out, out, out, dst, \ + dst_stride, stride2, stride3, stride4); \ + dst += stride4; \ + LSX_ST_8(out, out, out, out, out, out, out, out, dst, \ + dst_stride, stride2, stride3, stride4); \ +} + +INTRA_PREDICT_VALDC_16X16_LSX(127); +INTRA_PREDICT_VALDC_16X16_LSX(128); +INTRA_PREDICT_VALDC_16X16_LSX(129); + +#define INTRA_PREDICT_VALDC_32X32_LSX(val) \ +void ff_dc_##val##_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, const uint8_t *top) \ +{ \ + __m128i out = __lsx_vldi(val); \ + \ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ +} + +INTRA_PREDICT_VALDC_32X32_LSX(127); +INTRA_PREDICT_VALDC_32X32_LSX(128); +INTRA_PREDICT_VALDC_32X32_LSX(129); + +void ff_tm_4x4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + __m128i tmp0, tmp1, tmp2, tmp3, reg0, reg1; + __m128i src0, src1, src2, src3; + __m128i dst0, dst1, dst2, dst3; + + reg0 = __lsx_vreplgr2vr_h(top_left); + reg1 = __lsx_vld(src_top_ptr, 0); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, src_left, + 3, tmp3, tmp2, tmp1, tmp0); + DUP4_ARG2(__lsx_vilvl_b, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, reg1, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vhaddw_hu_bu, src0, src0, src1, src1, src2, src2, src3, + src3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vssub_hu, dst0, reg0, dst1, reg0, dst2, reg0, dst3, reg0, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vsat_hu, dst0, 7, dst1, 7, dst2, 7, dst3, 7, + dst0, dst1, dst2, dst3); + DUP2_ARG2(__lsx_vpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 2); +} + +void ff_tm_8x8_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i reg0, reg1; + + reg0 = __lsx_vreplgr2vr_h(top_left); + reg1 = __lsx_vld(src_top_ptr, 0); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, src_left, + 3, tmp7, tmp6, tmp5, tmp4); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 4, src_left, 5, src_left, 6, src_left, + 7, tmp3, tmp2, tmp1, tmp0); + DUP4_ARG2(__lsx_vilvl_b, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, reg1, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvl_b, tmp4, reg1, tmp5, reg1, tmp6, reg1, tmp7, reg1, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vhaddw_hu_bu, src0, src0, src1, src1, src2, src2, src3, + src3, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vhaddw_hu_bu, src4, src4, src5, src5, src6, src6, src7, + src7, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpickev_b, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src1, src2, src3); + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 1); +} + +void ff_tm_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i reg0, reg1; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + + reg0 = __lsx_vreplgr2vr_h(top_left); + reg1 = __lsx_vld(src_top_ptr, 0); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, src_left, + 3, tmp15, tmp14, tmp13, tmp12); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 4, src_left, 5, src_left, 6, src_left, + 7, tmp11, tmp10, tmp9, tmp8); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 8, src_left, 9, src_left, 10, + src_left, 11, tmp7, tmp6, tmp5, tmp4); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 12, src_left, 13, src_left, 14, + src_left, 15, tmp3, tmp2, tmp1, tmp0); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, + reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, + reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp4, reg1, tmp5, reg1, tmp6, reg1, tmp7, + reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp4, reg1, tmp5, reg1, tmp6, reg1, tmp7, + reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp8, reg1, tmp9, reg1, tmp10, reg1, tmp11, + reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp8, reg1, tmp9, reg1, tmp10, reg1, tmp11, + reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp8, tmp9, tmp10, tmp11); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp12, reg1, tmp13, reg1, tmp14, reg1, + tmp15, reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp12, reg1, tmp13, reg1, tmp14, reg1, + tmp15, reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp12, tmp13, tmp14, tmp15); + LSX_ST_8(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, dst, + dst_stride, stride2, stride3, stride4); +} + +void ff_tm_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + uint32_t loop_cnt; + __m128i tmp0, tmp1, tmp2, tmp3, reg0, reg1, reg2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + + reg0 = __lsx_vreplgr2vr_h(top_left); + DUP2_ARG2(__lsx_vld, src_top_ptr, 0, src_top_ptr, 16, reg1, reg2); + + src_left += 28; + for (loop_cnt = 8; loop_cnt--;) { + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, + src_left, 3, tmp3, tmp2, tmp1, tmp0); + src_left -= 4; + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, + tmp3, reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, + tmp3, reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, + reg0, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, + reg0, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp0, reg2, tmp1, reg2, tmp2, reg2, + tmp3, reg2, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp0, reg2, tmp1, reg2, tmp2, reg2, + tmp3, reg2, dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vssub_hu, dst0, reg0, dst1, reg0, dst2, reg0, dst3, + reg0, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vssub_hu, dst4, reg0, dst5, reg0, dst6, reg0, dst7, + reg0, dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, dst0, 7, dst1, 7, dst2, 7, dst3, 7, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vsat_hu, dst4, 7, dst5, 7, dst6, 7, dst7, 7, + dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, + src3, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vpackev_b, dst4, dst0, dst5, dst1, dst6, dst2, dst7, + dst3, dst0, dst1, dst2, dst3); + __lsx_vst(src0, dst, 0); + __lsx_vst(dst0, dst, 16); + dst += dst_stride; + __lsx_vst(src1, dst, 0); + __lsx_vst(dst1, dst, 16); + dst += dst_stride; + __lsx_vst(src2, dst, 0); + __lsx_vst(dst2, dst, 16); + dst += dst_stride; + __lsx_vst(src3, dst, 0); + __lsx_vst(dst3, dst, 16); + dst += dst_stride; + } +} diff --git a/libavcodec/loongarch/vp9_mc_lsx.c b/libavcodec/loongarch/vp9_mc_lsx.c new file mode 100644 index 0000000000..c6746fd87f --- /dev/null +++ b/libavcodec/loongarch/vp9_mc_lsx.c @@ -0,0 +1,2480 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp9dsp_loongarch.h" + +static const uint8_t mc_filt_mask_arr[16 * 3] = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + /* 4 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, + /* 4 width cases */ + 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 +}; + + +#define HORIZ_8TAP_4WID_4VECS_FILT(_src0, _src1, _src2, _src3, \ + _mask0, _mask1, _mask2, _mask3, \ + _filter0, _filter1, _filter2, _filter3, \ + _out0, _out1) \ +{ \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ + __m128i _reg0, _reg1, _reg2, _reg3; \ + \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask0, _src3, _src2, _mask0, \ + _tmp0, _tmp1); \ + DUP2_ARG2(__lsx_vdp2_h_b, _tmp0, _filter0, _tmp1, _filter0, _reg0, _reg1); \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask1, _src3, _src2, _mask1, \ + _tmp2, _tmp3); \ + DUP2_ARG3(__lsx_vdp2add_h_b, _reg0, _tmp2, _filter1, _reg1, _tmp3, \ + _filter1, _reg0, _reg1); \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask2, _src3, _src2, _mask2, \ + _tmp4, _tmp5); \ + DUP2_ARG2(__lsx_vdp2_h_b, _tmp4, _filter2, _tmp5, _filter2, _reg2, _reg3); \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask3, _src3, _src2, _mask3, \ + _tmp6, _tmp7); \ + DUP2_ARG3(__lsx_vdp2add_h_b, _reg2, _tmp6, _filter3, _reg3, _tmp7, \ + _filter3, _reg2, _reg3); \ + DUP2_ARG2(__lsx_vsadd_h, _reg0, _reg2, _reg1, _reg3, _out0, _out1); \ +} + +#define HORIZ_8TAP_8WID_4VECS_FILT(_src0, _src1, _src2, _src3, \ + _mask0, _mask1, _mask2, _mask3, \ + _filter0, _filter1, _filter2, _filter3, \ + _out0, _out1, _out2, _out3) \ +{ \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ + __m128i _reg0, _reg1, _reg2, _reg3, _reg4, _reg5, _reg6, _reg7; \ + \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask0, _src1, _src1, _mask0, _src2,\ + _src2, _mask0, _src3, _src3, _mask0, _tmp0, _tmp1, _tmp2, _tmp3);\ + DUP4_ARG2(__lsx_vdp2_h_b, _tmp0, _filter0, _tmp1, _filter0, _tmp2, \ + _filter0, _tmp3, _filter0, _reg0, _reg1, _reg2, _reg3); \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask2, _src1, _src1, _mask2, _src2,\ + _src2, _mask2, _src3, _src3, _mask2, _tmp0, _tmp1, _tmp2, _tmp3);\ + DUP4_ARG2(__lsx_vdp2_h_b, _tmp0, _filter2, _tmp1, _filter2, _tmp2, \ + _filter2, _tmp3, _filter2, _reg4, _reg5, _reg6, _reg7); \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask1, _src1, _src1, _mask1, _src2,\ + _src2, _mask1, _src3, _src3, _mask1, _tmp4, _tmp5, _tmp6, _tmp7);\ + DUP4_ARG3(__lsx_vdp2add_h_b, _reg0, _tmp4, _filter1, _reg1, _tmp5, \ + _filter1, _reg2, _tmp6, _filter1, _reg3, _tmp7, _filter1, _reg0, \ + _reg1, _reg2, _reg3); \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask3, _src1, _src1, _mask3, _src2,\ + _src2, _mask3, _src3, _src3, _mask3, _tmp4, _tmp5, _tmp6, _tmp7);\ + DUP4_ARG3(__lsx_vdp2add_h_b, _reg4, _tmp4, _filter3, _reg5, _tmp5, \ + _filter3, _reg6, _tmp6, _filter3, _reg7, _tmp7, _filter3, _reg4, \ + _reg5, _reg6, _reg7); \ + DUP4_ARG2(__lsx_vsadd_h, _reg0, _reg4, _reg1, _reg5, _reg2, _reg6, _reg3, \ + _reg7, _out0, _out1, _out2, _out3); \ +} + +#define FILT_8TAP_DPADD_S_H(_reg0, _reg1, _reg2, _reg3, \ + _filter0, _filter1, _filter2, _filter3) \ +( { \ + __m128i _vec0, _vec1; \ + \ + _vec0 = __lsx_vdp2_h_b(_reg0, _filter0); \ + _vec0 = __lsx_vdp2add_h_b(_vec0, _reg1, _filter1); \ + _vec1 = __lsx_vdp2_h_b(_reg2, _filter2); \ + _vec1 = __lsx_vdp2add_h_b(_vec1, _reg3, _filter3); \ + _vec0 = __lsx_vsadd_h(_vec0, _vec1); \ + \ + _vec0; \ +} ) + +#define HORIZ_8TAP_FILT(_src0, _src1, _mask0, _mask1, _mask2, _mask3, \ + _filt_h0, _filt_h1, _filt_h2, _filt_h3) \ +( { \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3; \ + __m128i _out; \ + \ + DUP4_ARG3(__lsx_vshuf_b, _src1, _src0, _mask0, _src1, _src0, _mask1, _src1,\ + _src0, _mask2, _src1, _src0, _mask3, _tmp0, _tmp1, _tmp2, _tmp3);\ + _out = FILT_8TAP_DPADD_S_H(_tmp0, _tmp1, _tmp2, _tmp3, _filt_h0, _filt_h1, \ + _filt_h2, _filt_h3); \ + _out = __lsx_vsrari_h(_out, 7); \ + _out = __lsx_vsat_h(_out, 7); \ + \ + _out; \ +} ) + +#define LSX_LD_4(_src, _stride, _src0, _src1, _src2, _src3) \ +{ \ + _src0 = __lsx_vld(_src, 0); \ + _src += _stride; \ + _src1 = __lsx_vld(_src, 0); \ + _src += _stride; \ + _src2 = __lsx_vld(_src, 0); \ + _src += _stride; \ + _src3 = __lsx_vld(_src, 0); \ +} + +static void common_hz_8t_4x4_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out, out0, out1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1); + out = __lsx_vssrarni_b_h(out1, out0, 7); + out = __lsx_vxori_b(out, 128); + __lsx_vstelm_w(out, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out, dst, 0, 3); +} + +static void common_hz_8t_4x8_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + uint8_t *_src = (uint8_t*)src - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 3); +} + +static void common_hz_8t_4w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + if (height == 4) { + common_hz_8t_4x4_lsx(src, src_stride, dst, dst_stride, filter); + } else if (height == 8) { + common_hz_8t_4x8_lsx(src, src_stride, dst, dst_stride, filter); + } +} + +static void common_hz_8t_8x4_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); +} + +static void common_hz_8t_8x8mult_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 2; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + uint8_t* _src = (uint8_t*)src - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + } +} + +static void common_hz_8t_8w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + if (height == 4) { + common_hz_8t_8x4_lsx(src, src_stride, dst, dst_stride, filter); + } else { + common_hz_8t_8x8mult_lsx(src, src_stride, dst, dst_stride, + filter, height); + } +} + +static void common_hz_8t_16w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 1; + int32_t stride = src_stride << 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + const uint8_t* _src = src + src_stride; + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src0, src2); + DUP2_ARG2(__lsx_vld, src, 8, _src, 8, src1, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + dst += dst_stride; + __lsx_vst(out1, dst, 0); + dst += dst_stride; + src += stride; + } +} + +static void common_hz_8t_32w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + src += src_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + src += src_stride; + + dst += dst_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + dst += dst_stride; + } +} + +static void common_hz_8t_64w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + int32_t loop_cnt = height; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + + DUP2_ARG2(__lsx_vld, src, 32, src, 48, src0, src2); + src3 = __lsx_vld(src, 56); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 32); + __lsx_vst(out1, dst, 48); + src += src_stride; + dst += dst_stride; + } +} + +static void common_vt_8t_4w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 2; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i reg0, reg1, reg2, reg3, reg4; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, tmp0, + tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, tmp4, tmp5); + DUP2_ARG2(__lsx_vilvl_d, tmp3, tmp0, tmp4, tmp1, reg0, reg1); + reg2 = __lsx_vilvl_d(tmp5, tmp2); + DUP2_ARG2(__lsx_vxori_b, reg0, 128, reg1, 128, reg0, reg1); + reg2 = __lsx_vxori_b(reg2, 128); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, reg3, reg4); + DUP2_ARG2(__lsx_vxori_b, reg3, 128, reg4, 128, reg3, reg4); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, reg3, filter0, filter1, + filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg1, reg2, reg3, reg4, filter0, filter1, + filter2, filter3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + + reg0 = reg2; + reg1 = reg3; + reg2 = reg4; + src6 = src10; + } +} + +static void common_vt_8t_8w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1, out2, out3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, tmp0, filter0, filter1, + filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, tmp1, filter0, filter1, + filter2, filter3); + out2 = FILT_8TAP_DPADD_S_H(reg1, reg2, tmp0, tmp2, filter0, filter1, + filter2, filter3); + out3 = FILT_8TAP_DPADD_S_H(reg4, reg5, tmp1, tmp3, filter0, filter1, + filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + reg0 = reg2; + reg1 = tmp0; + reg2 = tmp2; + reg3 = reg5; + reg4 = tmp1; + reg5 = tmp3; + src6 = src10; + } +} + +static void common_vt_8t_16w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filter0, filter1, filter2, filter3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i reg6, reg7, reg8, reg9, reg10, reg11; + __m128i tmp0, tmp1, tmp2, tmp3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg6, reg7, reg8, reg9); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, reg10, reg11); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, src9, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, src10, src9, + src4, src5, src7, src8); + tmp0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, src0, filter0, filter1, + filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, src1, filter0, filter1, + filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg6, reg7, reg8, src4, filter0, filter1, + filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg9, reg10, reg11, src5, filter0, filter1, + filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + tmp0 = FILT_8TAP_DPADD_S_H(reg1, reg2, src0, src2, filter0, filter1, + filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg4, reg5, src1, src3, filter0, filter1, + filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg7, reg8, src4, src7, filter0, filter1, + filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg10, reg11, src5, src8, filter0, filter1, + filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + reg0 = reg2; + reg1 = src0; + reg2 = src2; + reg3 = reg5; + reg4 = src1; + reg5 = src3; + reg6 = reg8; + reg7 = src4; + reg8 = src7; + reg9 = reg11; + reg10 = src5; + reg11 = src8; + src6 = src10; + } +} + +static void common_vt_8t_16w_mult_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height, + int32_t width) +{ + uint8_t *src_tmp; + uint8_t *dst_tmp; + uint32_t cnt = width >> 4; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filter0, filter1, filter2, filter3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i reg6, reg7, reg8, reg9, reg10, reg11; + __m128i tmp0, tmp1, tmp2, tmp3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + for (;cnt--;) { + uint32_t loop_cnt = height >> 2; + + src_tmp = _src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src5, src6); + src_tmp += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg6, reg7, reg8, reg9); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, reg10, reg11); + + for (;loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src8, src9); + src10 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, + 128, src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, + src10, src9, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, + src10, src9, src4, src5, src7, src8); + tmp0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, src0, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, src1, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg6, reg7, reg8, src4, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg9, reg10, reg11, src5, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst_tmp, 0); + __lsx_vstx(tmp1, dst_tmp, dst_stride); + tmp0 = FILT_8TAP_DPADD_S_H(reg1, reg2, src0, src2, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg4, reg5, src1, src3, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg7, reg8, src4, src7, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg10, reg11, src5, src8, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vstx(tmp0, dst_tmp, dst_stride2); + __lsx_vstx(tmp1, dst_tmp, dst_stride3); + dst_tmp += dst_stride4; + + reg0 = reg2; + reg1 = src0; + reg2 = src2; + reg3 = reg5; + reg4 = src1; + reg5 = src3; + reg6 = reg8; + reg7 = src4; + reg8 = src7; + reg9 = reg11; + reg10 = src5; + reg11 = src8; + src6 = src10; + } + _src += 16; + dst += 16; + } +} + +static void common_vt_8t_32w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + common_vt_8t_16w_mult_lsx(src, src_stride, dst, dst_stride, filter, height, 32); +} + +static void common_vt_8t_64w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + common_vt_8t_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 64); +} + +static void common_hv_8ht_8vt_4w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i out0, out1; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3 - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, 4, + filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + tmp0 = HORIZ_8TAP_FILT(src0, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp2 = HORIZ_8TAP_FILT(src2, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = HORIZ_8TAP_FILT(src4, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp5 = HORIZ_8TAP_FILT(src5, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG3(__lsx_vshuf_b, tmp2, tmp0, shuff, tmp4, tmp2, shuff, tmp1, tmp3); + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP2_ARG2(__lsx_vpackev_b, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + tmp2 = __lsx_vpackev_b(tmp5, tmp4); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + tmp3 = HORIZ_8TAP_FILT(src7, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = __lsx_vshuf_b(tmp3, tmp5, shuff); + tmp4 = __lsx_vpackev_b(tmp3, tmp4); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp4, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src1 = HORIZ_8TAP_FILT(src9, src10, mask0, mask1, mask2, mask3, + filt_hz0, filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vshuf_b(src1, tmp3, shuff); + src0 = __lsx_vpackev_b(src1, src0); + out1 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp4, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + + tmp5 = src1; + tmp0 = tmp2; + tmp1 = tmp4; + tmp2 = src0; + } +} + +static void common_hv_8ht_8vt_8w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m128i out0, out1; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3 - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, + 4, filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + src0 = HORIZ_8TAP_FILT(src0, src0, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = HORIZ_8TAP_FILT(src1, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src2 = HORIZ_8TAP_FILT(src2, src2, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src3 = HORIZ_8TAP_FILT(src3, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src4 = HORIZ_8TAP_FILT(src4, src4, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src5 = HORIZ_8TAP_FILT(src5, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src6 = HORIZ_8TAP_FILT(src6, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP4_ARG2(__lsx_vpackev_b, src1, src0, src3, src2, src5, src4, + src2, src1, tmp0, tmp1, tmp2, tmp4); + DUP2_ARG2(__lsx_vpackev_b, src4, src3, src6, src5, tmp5, tmp6); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + src7 = HORIZ_8TAP_FILT(src7, src7, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp3 = __lsx_vpackev_b(src7, src6); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp3, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src8 = HORIZ_8TAP_FILT(src8, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vpackev_b(src8, src7); + out1 = FILT_8TAP_DPADD_S_H(tmp4, tmp5, tmp6, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src9 = HORIZ_8TAP_FILT(src9, src9, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = __lsx_vpackev_b(src9, src8); + src3 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp3, src1, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src10 = HORIZ_8TAP_FILT(src10, src10, mask0, mask1, mask2, mask3, + filt_hz0, filt_hz1, filt_hz2, filt_hz3); + src2 = __lsx_vpackev_b(src10, src9); + src4 = FILT_8TAP_DPADD_S_H(tmp5, tmp6, src0, src2, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, src4, src3, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + src6 = src10; + tmp0 = tmp2; + tmp1 = tmp3; + tmp2 = src1; + tmp4 = tmp6; + tmp5 = src0; + tmp6 = src2; + } +} + +static void common_hv_8ht_8vt_16w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + common_hv_8ht_8vt_8w_lsx(src, src_stride, dst, dst_stride, filter_horiz, + filter_vert, height); + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_32w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 4; multiple8_cnt--;) { + common_hv_8ht_8vt_8w_lsx(src, src_stride, dst, dst_stride, filter_horiz, + filter_vert, height); + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_64w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 8; multiple8_cnt--;) { + common_hv_8ht_8vt_8w_lsx(src, src_stride, dst, dst_stride, filter_horiz, + filter_vert, height); + src += 8; + dst += 8; + } +} + +static void copy_width8_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3; + + for (;cnt--;) { + src0 = __lsx_vldrepl_d(src, 0); + src += src_stride; + src1 = __lsx_vldrepl_d(src, 0); + src += src_stride; + src2 = __lsx_vldrepl_d(src, 0); + src += src_stride; + src3 = __lsx_vldrepl_d(src, 0); + src += src_stride; + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + } +} + +static void copy_width16_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t *_src = (uint8_t*)src; + + for (;cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + __lsx_vst(src0, dst, 0); + __lsx_vstx(src1, dst, dst_stride); + __lsx_vstx(src2, dst, dst_stride2); + __lsx_vstx(src3, dst, dst_stride3); + dst += dst_stride4; + } +} + +static void copy_width32_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *src_tmp1 = (uint8_t*)src; + uint8_t *dst_tmp1 = dst; + uint8_t *src_tmp2 = src_tmp1 + 16; + uint8_t *dst_tmp2 = dst_tmp1 + 16; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + + for (;cnt--;) { + src0 = __lsx_vld(src_tmp1, 0); + DUP2_ARG2(__lsx_vldx, src_tmp1, src_stride, src_tmp1, src_stride2, + src1, src2); + src3 = __lsx_vldx(src_tmp1, src_stride3); + src_tmp1 += src_stride4; + + src4 = __lsx_vld(src_tmp2, 0); + DUP2_ARG2(__lsx_vldx, src_tmp2, src_stride, src_tmp2, src_stride2, + src5, src6); + src7 = __lsx_vldx(src_tmp2, src_stride3); + src_tmp2 += src_stride4; + + __lsx_vst(src0, dst_tmp1, 0); + __lsx_vstx(src1, dst_tmp1, dst_stride); + __lsx_vstx(src2, dst_tmp1, dst_stride2); + __lsx_vstx(src3, dst_tmp1, dst_stride3); + dst_tmp1 += dst_stride4; + __lsx_vst(src4, dst_tmp2, 0); + __lsx_vstx(src5, dst_tmp2, dst_stride); + __lsx_vstx(src6, dst_tmp2, dst_stride2); + __lsx_vstx(src7, dst_tmp2, dst_stride3); + dst_tmp2 += dst_stride4; + } +} + +static void copy_width64_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + + for (;cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src0, src1, src2, src3); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src4, src5, src6, src7); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src8, src9, src10, src11); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src12, src13, src14, src15); + src += src_stride; + __lsx_vst(src0, dst, 0); + __lsx_vst(src1, dst, 16); + __lsx_vst(src2, dst, 32); + __lsx_vst(src3, dst, 48); + dst += dst_stride; + __lsx_vst(src4, dst, 0); + __lsx_vst(src5, dst, 16); + __lsx_vst(src6, dst, 32); + __lsx_vst(src7, dst, 48); + dst += dst_stride; + __lsx_vst(src8, dst, 0); + __lsx_vst(src9, dst, 16); + __lsx_vst(src10, dst, 32); + __lsx_vst(src11, dst, 48); + dst += dst_stride; + __lsx_vst(src12, dst, 0); + __lsx_vst(src13, dst, 16); + __lsx_vst(src14, dst, 32); + __lsx_vst(src15, dst, 48); + dst += dst_stride; + } +} + +static void common_hz_8t_and_aver_dst_4x4_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1; + __m128i dst0, dst1, dst2, dst3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, + filter0, filter1, filter2, filter3, tmp0, tmp1); + dst0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + dst1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + dst2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + dst3 = __lsx_vldrepl_w(dst_tmp, 0); + dst0 = __lsx_vilvl_w(dst1, dst0); + dst1 = __lsx_vilvl_w(dst3, dst2); + dst0 = __lsx_vilvl_d(dst1, dst0); + tmp0 = __lsx_vssrarni_b_h(tmp1, tmp0, 7); + tmp0 = __lsx_vxori_b(tmp0, 128); + dst0 = __lsx_vavgr_bu(tmp0, dst0); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 3); +} + +static void common_hz_8t_and_aver_dst_4x8_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3, tmp0, tmp1, tmp2, tmp3; + __m128i dst0, dst1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + src += src_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + tmp0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp3 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp0 = __lsx_vilvl_w(tmp1, tmp0); + tmp1 = __lsx_vilvl_w(tmp3, tmp2); + dst0 = __lsx_vilvl_d(tmp1, tmp0); + + tmp0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp3 = __lsx_vldrepl_w(dst_tmp, 0); + tmp0 = __lsx_vilvl_w(tmp1, tmp0); + tmp1 = __lsx_vilvl_w(tmp3, tmp2); + dst1 = __lsx_vilvl_d(tmp1, tmp0); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, + filter0, filter1, filter2, filter3, tmp0, tmp1); + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, + filter0, filter1, filter2, filter3, tmp2, tmp3); + DUP4_ARG3(__lsx_vssrarni_b_h, tmp0, tmp0, 7, tmp1, tmp1, 7, tmp2, tmp2, 7, + tmp3, tmp3, 7, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, dst0, tmp1, dst1, dst0, dst1); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 3); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 3); +} + +static void common_hz_8t_and_aver_dst_4w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + if (height == 4) { + common_hz_8t_and_aver_dst_4x4_lsx(src, src_stride, dst, dst_stride, filter); + } else if (height == 8) { + common_hz_8t_and_aver_dst_4x8_lsx(src, src_stride, dst, dst_stride, filter); + } +} + +static void common_hz_8t_and_aver_dst_8w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + int32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i dst0, dst1, dst2, dst3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride2 + src_stride; + int32_t src_stride4 = src_stride2 << 1; + uint8_t *_src = (uint8_t*)src - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3,filter0, filter1, filter2, filter3, tmp0, tmp1, tmp2, tmp3); + dst0 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + dst1 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + dst2 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + dst3 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, dst1, dst0, dst3, dst2, dst0, dst1); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, dst0, tmp1, dst1, dst0, dst1); + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 1); + dst += dst_stride; + } +} + +static void common_hz_8t_and_aver_dst_16w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + int32_t loop_cnt = height >> 1; + int32_t dst_stride2 = dst_stride << 1; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3, dst0, dst1, dst2, dst3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 8, src0, src1); + src += src_stride; + DUP2_ARG2(__lsx_vld, src, 0, src, 8, src2, src3); + src += src_stride; + dst0 = __lsx_vld(dst_tmp, 0); + dst1 = __lsx_vldx(dst_tmp, dst_stride); + dst_tmp += dst_stride2; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, src2, src2, + mask0, src3, src3, mask0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, src2, src2, + mask1, src3, src3, mask1, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, src2, src2, + mask2, src3, src3, mask2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, src2, src2, + mask3, src3, src3, mask3, tmp12, tmp13, tmp14, tmp15); + DUP4_ARG2(__lsx_vdp2_h_b, tmp0, filter0, tmp1, filter0, tmp2, filter0, tmp3, + filter0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vdp2_h_b, tmp8, filter2, tmp9, filter2, tmp10, filter2, tmp11, + filter2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp0, tmp4, filter1, tmp1, tmp5, filter1, tmp2, + tmp6, filter1, tmp3, tmp7, filter1, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp8, tmp12, filter3, tmp9, tmp13, filter3, tmp10, + tmp14, filter3, tmp11, tmp15, filter3, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vsadd_h, tmp0, tmp4, tmp1, tmp5, tmp2, tmp6, tmp3, tmp7, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, dst2, dst3); + DUP2_ARG2(__lsx_vxori_b, dst2, 128, dst3, 128, dst2, dst3); + DUP2_ARG2(__lsx_vavgr_bu, dst0, dst2, dst1, dst3, dst0, dst1); + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + dst += dst_stride2; + } +} + +static void common_hz_8t_and_aver_dst_32w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + uint32_t loop_cnt = height; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3, dst0, dst1; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + src += src_stride; + DUP2_ARG2(__lsx_vld, dst_tmp, 0, dst, 16, dst0, dst1); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, src2, + src2, mask0, src3, src3, mask0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, src2, + src2, mask1, src3, src3, mask1, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, src2, + src2, mask2, src3, src3, mask2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, src2, + src2, mask3, src3, src3, mask3, tmp12, tmp13, tmp14, tmp15); + DUP4_ARG2(__lsx_vdp2_h_b, tmp0, filter0, tmp1, filter0, tmp2, filter0, + tmp3, filter0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vdp2_h_b, tmp8, filter2, tmp9, filter2, tmp10, filter2, + tmp11, filter2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp0, tmp4, filter1, tmp1, tmp5, filter1, + tmp2, tmp6, filter1, tmp3, tmp7, filter1, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp8, tmp12, filter3, tmp9, tmp13, filter3, + tmp10, tmp14, filter3, tmp11, tmp15, filter3, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vsadd_h, tmp0, tmp4, tmp1, tmp5, tmp2, tmp6, tmp3, tmp7, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + DUP2_ARG2(__lsx_vavgr_bu, dst0, tmp0, dst1, tmp1, dst0, dst1); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + dst += dst_stride; + } +} + +static void common_hz_8t_and_aver_dst_64w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + int32_t loop_cnt = height; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3, dst0, dst1; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP2_ARG2(__lsx_vld, dst, 0, dst, 16, dst0, dst1); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + DUP2_ARG2(__lsx_vavgr_bu, out0, dst0, out1, dst1, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + + DUP2_ARG2(__lsx_vld, src, 32, src, 48, src0, src2); + src3 = __lsx_vld(src, 56); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP2_ARG2(__lsx_vld, dst, 32, dst, 48, dst0, dst1); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + DUP2_ARG2(__lsx_vavgr_bu, out0, dst0, out1, dst1, out0, out1); + __lsx_vst(out0, dst, 32); + __lsx_vst(out1, dst, 48); + src += src_stride; + dst += dst_stride; + } +} + +static void common_vt_8t_and_aver_dst_4w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i reg0, reg1, reg2, reg3, reg4; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, tmp4, tmp5); + DUP2_ARG2(__lsx_vilvl_d, tmp3, tmp0, tmp4, tmp1, reg0, reg1); + reg2 = __lsx_vilvl_d(tmp5, tmp2); + DUP2_ARG2(__lsx_vxori_b, reg0, 128, reg1, 128, reg0, reg1); + reg2 = __lsx_vxori_b(reg2, 128); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src3 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_w, src1, src0, src3, src2, src0, src1); + src0 = __lsx_vilvl_d(src1, src0); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, reg3, reg4); + DUP2_ARG2(__lsx_vxori_b, reg3, 128, reg4, 128, reg3, reg4); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, reg3, filter0, + filter1, filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg1, reg2, reg3, reg4, filter0, + filter1, filter2, filter3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + out0 = __lsx_vavgr_bu(out0, src0); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + reg0 = reg2; + reg1 = reg3; + reg2 = reg4; + src6 = src10; + } +} + +static void common_vt_8t_and_aver_dst_8w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1, out2, out3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, + src1, reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src0 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src1 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src2 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src3 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, src1, src0, src3, src2, src0, src1); + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, tmp0, filter0, + filter1, filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, tmp1, filter0, + filter1, filter2, filter3); + out2 = FILT_8TAP_DPADD_S_H(reg1, reg2, tmp0, tmp2, filter0, + filter1, filter2, filter3); + out3 = FILT_8TAP_DPADD_S_H(reg4, reg5, tmp1, tmp3, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + DUP2_ARG2(__lsx_vavgr_bu, out0, src0, out1, src1, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + reg0 = reg2; + reg1 = tmp0; + reg2 = tmp2; + reg3 = reg5; + reg4 = tmp1; + reg5 = tmp3; + src6 = src10; + } +} + +static void common_vt_8t_and_aver_dst_16w_mult_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t height, + int32_t width) +{ + uint8_t *src_tmp; + uint32_t cnt = width >> 4; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filter0, filter1, filter2, filter3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i reg6, reg7, reg8, reg9, reg10, reg11; + __m128i tmp0, tmp1, tmp2, tmp3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t *_src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + for (;cnt--;) { + uint32_t loop_cnt = height >> 2; + uint8_t *dst_reg = dst; + + src_tmp = _src; + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src5, src6); + src_tmp += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg6, reg7, reg8, reg9); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, reg10, reg11); + + for (;loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src8, src9); + src10 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, + 128, src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, + src10, src9, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, + src10, src9, src4, src5, src7, src8); + tmp0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, src0, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, src1, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg6, reg7, reg8, src4, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg9, reg10, reg11, src5, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + tmp2 = __lsx_vld(dst_reg, 0); + tmp3 = __lsx_vldx(dst_reg, dst_stride); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, tmp2, tmp1, tmp3, tmp0, tmp1); + __lsx_vst(tmp0, dst_reg, 0); + __lsx_vstx(tmp1, dst_reg, dst_stride); + tmp0 = FILT_8TAP_DPADD_S_H(reg1, reg2, src0, src2, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg4, reg5, src1, src3, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg7, reg8, src4, src7, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg10, reg11, src5, src8, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + tmp2 = __lsx_vldx(dst_reg, dst_stride2); + tmp3 = __lsx_vldx(dst_reg, dst_stride3); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, tmp2, tmp1, tmp3, tmp0, tmp1); + __lsx_vstx(tmp0, dst_reg, dst_stride2); + __lsx_vstx(tmp1, dst_reg, dst_stride3); + dst_reg += dst_stride4; + + reg0 = reg2; + reg1 = src0; + reg2 = src2; + reg3 = reg5; + reg4 = src1; + reg5 = src3; + reg6 = reg8; + reg7 = src4; + reg8 = src7; + reg9 = reg11; + reg10 = src5; + reg11 = src8; + src6 = src10; + } + _src += 16; + dst += 16; + } +} + +static void common_vt_8t_and_aver_dst_16w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + common_vt_8t_and_aver_dst_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 16); +} + +static void common_vt_8t_and_aver_dst_32w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + common_vt_8t_and_aver_dst_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 32); +} + +static void common_vt_8t_and_aver_dst_64w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + common_vt_8t_and_aver_dst_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 64); +} + +static void common_hv_8ht_8vt_and_aver_dst_4w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i out0, out1; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - 3 - src_stride3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, + 4, filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + tmp0 = HORIZ_8TAP_FILT(src0, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp2 = HORIZ_8TAP_FILT(src2, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = HORIZ_8TAP_FILT(src4, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp5 = HORIZ_8TAP_FILT(src5, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG3(__lsx_vshuf_b, tmp2, tmp0, shuff, tmp4, tmp2, shuff, tmp1, tmp3); + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP2_ARG2(__lsx_vpackev_b, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + tmp2 = __lsx_vpackev_b(tmp5, tmp4); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src3 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src4 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src5 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_w, src3, src2, src5, src4, src2, src3); + src2 = __lsx_vilvl_d(src3, src2); + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + tmp3 = HORIZ_8TAP_FILT(src7, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = __lsx_vshuf_b(tmp3, tmp5, shuff); + tmp4 = __lsx_vpackev_b(tmp3, tmp4); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp4, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src1 = HORIZ_8TAP_FILT(src9, src10, mask0, mask1, mask2, mask3, + filt_hz0, filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vshuf_b(src1, tmp3, shuff); + src0 = __lsx_vpackev_b(src1, src0); + out1 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp4, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + out0 = __lsx_vavgr_bu(out0, src2); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + + tmp5 = src1; + tmp0 = tmp2; + tmp1 = tmp4; + tmp2 = src0; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_8w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m128i out0, out1; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - 3 - src_stride3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, + 4, filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + src0 = HORIZ_8TAP_FILT(src0, src0, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = HORIZ_8TAP_FILT(src1, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src2 = HORIZ_8TAP_FILT(src2, src2, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src3 = HORIZ_8TAP_FILT(src3, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src4 = HORIZ_8TAP_FILT(src4, src4, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src5 = HORIZ_8TAP_FILT(src5, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src6 = HORIZ_8TAP_FILT(src6, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP4_ARG2(__lsx_vpackev_b, src1, src0, src3, src2, src5, src4, + src2, src1, tmp0, tmp1, tmp2, tmp4); + DUP2_ARG2(__lsx_vpackev_b, src4, src3, src6, src5, tmp5, tmp6); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + src7 = HORIZ_8TAP_FILT(src7, src7, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp3 = __lsx_vpackev_b(src7, src6); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp3, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src8 = HORIZ_8TAP_FILT(src8, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vpackev_b(src8, src7); + out1 = FILT_8TAP_DPADD_S_H(tmp4, tmp5, tmp6, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src9 = HORIZ_8TAP_FILT(src9, src9, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = __lsx_vpackev_b(src9, src8); + src3 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp3, src1, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src10 = HORIZ_8TAP_FILT(src10, src10, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src2 = __lsx_vpackev_b(src10, src9); + src4 = FILT_8TAP_DPADD_S_H(tmp5, tmp6, src0, src2, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, src4, src3, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + src5 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src7 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src8 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src9 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, src7, src5, src9, src8, src5, src7); + DUP2_ARG2(__lsx_vavgr_bu, out0, src5, out1, src7, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + src6 = src10; + tmp0 = tmp2; + tmp1 = tmp3; + tmp2 = src1; + tmp4 = tmp6; + tmp5 = src0; + tmp6 = src2; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_16w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + common_hv_8ht_8vt_and_aver_dst_8w_lsx(src, src_stride, dst, dst_stride, + filter_horiz, filter_vert, + height); + + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_32w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 4; multiple8_cnt--;) { + common_hv_8ht_8vt_and_aver_dst_8w_lsx(src, src_stride, dst, dst_stride, + filter_horiz, filter_vert, + height); + + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_64w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 8; multiple8_cnt--;) { + common_hv_8ht_8vt_and_aver_dst_8w_lsx(src, src_stride, dst, dst_stride, + filter_horiz, filter_vert, + height); + + src += 8; + dst += 8; + } +} + +static void avg_width8_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, dst0, dst1; + __m128i tmp0, tmp1, tmp2, tmp3; + + for (;cnt--;) { + tmp0 = __lsx_vldrepl_d(src, 0); + src += src_stride; + tmp1 = __lsx_vldrepl_d(src, 0); + src += src_stride; + tmp2 = __lsx_vldrepl_d(src, 0); + src += src_stride; + tmp3 = __lsx_vldrepl_d(src, 0); + src += src_stride; + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, src0, src1); + tmp0 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + tmp1 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + tmp2 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + tmp3 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, dst0, dst1); + DUP2_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, dst0, dst1); + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 1); + dst += dst_stride; + } +} + +static void avg_width16_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3; + __m128i dst0, dst1, dst2, dst3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t* _src = (uint8_t*)src; + + for (;cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + + dst0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, dst_stride2, + dst1, dst2); + dst3 = __lsx_vldx(dst, dst_stride3); + DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, + src2, dst2, src3, dst3, dst0, dst1, dst2, dst3); + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + __lsx_vstx(dst2, dst, dst_stride2); + __lsx_vstx(dst3, dst, dst_stride3); + dst += dst_stride4; + } +} + +static void avg_width32_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *src_tmp1 = (uint8_t*)src; + uint8_t *src_tmp2 = src_tmp1 + 16; + uint8_t *dst_tmp1, *dst_tmp2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + + dst_tmp1 = dst; + dst_tmp2 = dst + 16; + for (;cnt--;) { + src0 = __lsx_vld(src_tmp1, 0); + DUP2_ARG2(__lsx_vldx, src_tmp1, src_stride, src_tmp1, src_stride2, + src2, src4); + src6 = __lsx_vldx(src_tmp1, src_stride3); + src_tmp1 += src_stride4; + + src1 = __lsx_vld(src_tmp2, 0); + DUP2_ARG2(__lsx_vldx, src_tmp2, src_stride, src_tmp2, src_stride2, + src3, src5); + src7 = __lsx_vldx(src_tmp2, src_stride3); + src_tmp2 += src_stride4; + + dst0 = __lsx_vld(dst_tmp1, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp1, dst_stride, dst_tmp1, dst_stride2, + dst2, dst4); + dst6 = __lsx_vldx(dst_tmp1, dst_stride3); + dst1 = __lsx_vld(dst_tmp2, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp2, dst_stride, dst_tmp2, dst_stride2, + dst3, dst5); + dst7 = __lsx_vldx(dst_tmp2, dst_stride3); + + DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, + src2, dst2, src3, dst3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, + src6, dst6, src7, dst7, dst4, dst5, dst6, dst7); + __lsx_vst(dst0, dst_tmp1, 0); + __lsx_vstx(dst2, dst_tmp1, dst_stride); + __lsx_vstx(dst4, dst_tmp1, dst_stride2); + __lsx_vstx(dst6, dst_tmp1, dst_stride3); + dst_tmp1 += dst_stride4; + __lsx_vst(dst1, dst_tmp2, 0); + __lsx_vstx(dst3, dst_tmp2, dst_stride); + __lsx_vstx(dst5, dst_tmp2, dst_stride2); + __lsx_vstx(dst7, dst_tmp2, dst_stride3); + dst_tmp2 += dst_stride4; + } +} + +static void avg_width64_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i dst8, dst9, dst10, dst11, dst12, dst13, dst14, dst15; + + for (;cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src0, src1, src2, src3); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src4, src5, src6, src7); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src8, src9, src10, src11); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src12, src13, src14, src15); + src += src_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst0, dst1, dst2, dst3); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst4, dst5, dst6, dst7); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst8, dst9, dst10, dst11); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst12, dst13, dst14, dst15); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, + src2, dst2, src3, dst3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, + src6, dst6, src7, dst7, dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vavgr_bu, src8, dst8, src9, dst9, src10, + dst10, src11, dst11, dst8, dst9, dst10, dst11); + DUP4_ARG2(__lsx_vavgr_bu, src12, dst12, src13, dst13, src14, + dst14, src15, dst15, dst12, dst13, dst14, dst15); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + __lsx_vst(dst2, dst, 32); + __lsx_vst(dst3, dst, 48); + dst += dst_stride; + __lsx_vst(dst4, dst, 0); + __lsx_vst(dst5, dst, 16); + __lsx_vst(dst6, dst, 32); + __lsx_vst(dst7, dst, 48); + dst += dst_stride; + __lsx_vst(dst8, dst, 0); + __lsx_vst(dst9, dst, 16); + __lsx_vst(dst10, dst, 32); + __lsx_vst(dst11, dst, 48); + dst += dst_stride; + __lsx_vst(dst12, dst, 0); + __lsx_vst(dst13, dst, 16); + __lsx_vst(dst14, dst, 32); + __lsx_vst(dst15, dst, 48); + dst += dst_stride; + } +} + +static const int8_t vp9_subpel_filters_lsx[3][15][8] = { + [FILTER_8TAP_REGULAR] = { + {0, 1, -5, 126, 8, -3, 1, 0}, + {-1, 3, -10, 122, 18, -6, 2, 0}, + {-1, 4, -13, 118, 27, -9, 3, -1}, + {-1, 4, -16, 112, 37, -11, 4, -1}, + {-1, 5, -18, 105, 48, -14, 4, -1}, + {-1, 5, -19, 97, 58, -16, 5, -1}, + {-1, 6, -19, 88, 68, -18, 5, -1}, + {-1, 6, -19, 78, 78, -19, 6, -1}, + {-1, 5, -18, 68, 88, -19, 6, -1}, + {-1, 5, -16, 58, 97, -19, 5, -1}, + {-1, 4, -14, 48, 105, -18, 5, -1}, + {-1, 4, -11, 37, 112, -16, 4, -1}, + {-1, 3, -9, 27, 118, -13, 4, -1}, + {0, 2, -6, 18, 122, -10, 3, -1}, + {0, 1, -3, 8, 126, -5, 1, 0}, + }, [FILTER_8TAP_SHARP] = { + {-1, 3, -7, 127, 8, -3, 1, 0}, + {-2, 5, -13, 125, 17, -6, 3, -1}, + {-3, 7, -17, 121, 27, -10, 5, -2}, + {-4, 9, -20, 115, 37, -13, 6, -2}, + {-4, 10, -23, 108, 48, -16, 8, -3}, + {-4, 10, -24, 100, 59, -19, 9, -3}, + {-4, 11, -24, 90, 70, -21, 10, -4}, + {-4, 11, -23, 80, 80, -23, 11, -4}, + {-4, 10, -21, 70, 90, -24, 11, -4}, + {-3, 9, -19, 59, 100, -24, 10, -4}, + {-3, 8, -16, 48, 108, -23, 10, -4}, + {-2, 6, -13, 37, 115, -20, 9, -4}, + {-2, 5, -10, 27, 121, -17, 7, -3}, + {-1, 3, -6, 17, 125, -13, 5, -2}, + {0, 1, -3, 8, 127, -7, 3, -1}, + }, [FILTER_8TAP_SMOOTH] = { + {-3, -1, 32, 64, 38, 1, -3, 0}, + {-2, -2, 29, 63, 41, 2, -3, 0}, + {-2, -2, 26, 63, 43, 4, -4, 0}, + {-2, -3, 24, 62, 46, 5, -4, 0}, + {-2, -3, 21, 60, 49, 7, -4, 0}, + {-1, -4, 18, 59, 51, 9, -4, 0}, + {-1, -4, 16, 57, 53, 12, -4, -1}, + {-1, -4, 14, 55, 55, 14, -4, -1}, + {-1, -4, 12, 53, 57, 16, -4, -1}, + {0, -4, 9, 51, 59, 18, -4, -1}, + {0, -4, 7, 49, 60, 21, -3, -2}, + {0, -4, 5, 46, 62, 24, -3, -2}, + {0, -4, 4, 43, 63, 26, -2, -2}, + {0, -3, 2, 41, 63, 29, -2, -2}, + {0, -3, 1, 38, 64, 32, -1, -3}, + } +}; + +#define VP9_8TAP_LOONGARCH_LSX_FUNC(SIZE, type, type_idx) \ +void ff_put_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + \ + common_hz_8t_##SIZE##w_lsx(src, srcstride, dst, dststride, filter, h); \ +} \ + \ +void ff_put_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_vt_8t_##SIZE##w_lsx(src, srcstride, dst, dststride, filter, h); \ +} \ + \ +void ff_put_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *hfilter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + const int8_t *vfilter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_hv_8ht_8vt_##SIZE##w_lsx(src, srcstride, dst, dststride, hfilter, \ + vfilter, h); \ +} \ + \ +void ff_avg_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + \ + common_hz_8t_and_aver_dst_##SIZE##w_lsx(src, srcstride, dst, \ + dststride, filter, h); \ +} \ + \ +void ff_avg_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_vt_8t_and_aver_dst_##SIZE##w_lsx(src, srcstride, dst, dststride, \ + filter, h); \ +} \ + \ +void ff_avg_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *hfilter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + const int8_t *vfilter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_hv_8ht_8vt_and_aver_dst_##SIZE##w_lsx(src, srcstride, dst, \ + dststride, hfilter, \ + vfilter, h); \ +} + +#define VP9_COPY_LOONGARCH_LSX_FUNC(SIZE) \ +void ff_copy##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + \ + copy_width##SIZE##_lsx(src, srcstride, dst, dststride, h); \ +} \ +void ff_avg##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + \ + avg_width##SIZE##_lsx(src, srcstride, dst, dststride, h); \ +} + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, regular, FILTER_8TAP_REGULAR); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, sharp, FILTER_8TAP_SHARP); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, smooth, FILTER_8TAP_SMOOTH); + +VP9_COPY_LOONGARCH_LSX_FUNC(64); +VP9_COPY_LOONGARCH_LSX_FUNC(32); +VP9_COPY_LOONGARCH_LSX_FUNC(16); +VP9_COPY_LOONGARCH_LSX_FUNC(8); + +#undef VP9_8TAP_LOONGARCH_LSX_FUNC +#undef VP9_COPY_LOONGARCH_LSX_FUNC diff --git a/libavcodec/loongarch/vp9dsp_init_loongarch.c b/libavcodec/loongarch/vp9dsp_init_loongarch.c new file mode 100644 index 0000000000..c1e01b4558 --- /dev/null +++ b/libavcodec/loongarch/vp9dsp_init_loongarch.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/vp9dsp.h" +#include "vp9dsp_loongarch.h" + +#define init_subpel1(idx1, idx2, idxh, idxv, sz, dir, type) \ + dsp->mc[idx1][FILTER_8TAP_SMOOTH ][idx2][idxh][idxv] = \ + ff_##type##_8tap_smooth_##sz##dir##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_REGULAR][idx2][idxh][idxv] = \ + ff_##type##_8tap_regular_##sz##dir##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_SHARP ][idx2][idxh][idxv] = \ + ff_##type##_8tap_sharp_##sz##dir##_lsx; + +#define init_subpel2(idx, idxh, idxv, dir, type) \ + init_subpel1(0, idx, idxh, idxv, 64, dir, type); \ + init_subpel1(1, idx, idxh, idxv, 32, dir, type); \ + init_subpel1(2, idx, idxh, idxv, 16, dir, type); \ + init_subpel1(3, idx, idxh, idxv, 8, dir, type); \ + init_subpel1(4, idx, idxh, idxv, 4, dir, type); + +#define init_subpel3(idx, type) \ + init_subpel2(idx, 1, 0, h, type); \ + init_subpel2(idx, 0, 1, v, type); \ + init_subpel2(idx, 1, 1, hv, type); + +#define init_fpel(idx1, idx2, sz, type) \ + dsp->mc[idx1][FILTER_8TAP_SMOOTH ][idx2][0][0] = ff_##type##sz##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_REGULAR][idx2][0][0] = ff_##type##sz##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_SHARP ][idx2][0][0] = ff_##type##sz##_lsx; \ + dsp->mc[idx1][FILTER_BILINEAR ][idx2][0][0] = ff_##type##sz##_lsx; + +#define init_copy(idx, sz) \ + init_fpel(idx, 0, sz, copy); \ + init_fpel(idx, 1, sz, avg); + +#define init_intra_pred1_lsx(tx, sz) \ + dsp->intra_pred[tx][VERT_PRED] = ff_vert_##sz##_lsx; \ + dsp->intra_pred[tx][HOR_PRED] = ff_hor_##sz##_lsx; \ + dsp->intra_pred[tx][DC_PRED] = ff_dc_##sz##_lsx; \ + dsp->intra_pred[tx][LEFT_DC_PRED] = ff_dc_left_##sz##_lsx; \ + dsp->intra_pred[tx][TOP_DC_PRED] = ff_dc_top_##sz##_lsx; \ + dsp->intra_pred[tx][DC_128_PRED] = ff_dc_128_##sz##_lsx; \ + dsp->intra_pred[tx][DC_127_PRED] = ff_dc_127_##sz##_lsx; \ + dsp->intra_pred[tx][DC_129_PRED] = ff_dc_129_##sz##_lsx; \ + dsp->intra_pred[tx][TM_VP8_PRED] = ff_tm_##sz##_lsx; \ + +#define init_intra_pred2_lsx(tx, sz) \ + dsp->intra_pred[tx][DC_PRED] = ff_dc_##sz##_lsx; \ + dsp->intra_pred[tx][LEFT_DC_PRED] = ff_dc_left_##sz##_lsx; \ + dsp->intra_pred[tx][TOP_DC_PRED] = ff_dc_top_##sz##_lsx; \ + dsp->intra_pred[tx][TM_VP8_PRED] = ff_tm_##sz##_lsx; \ + +av_cold void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_lsx(cpu_flags)) + if (bpp == 8) { + init_subpel3(0, put); + init_subpel3(1, avg); + init_copy(0, 64); + init_copy(1, 32); + init_copy(2, 16); + init_copy(3, 8); + init_intra_pred1_lsx(TX_16X16, 16x16); + init_intra_pred1_lsx(TX_32X32, 32x32); + init_intra_pred2_lsx(TX_4X4, 4x4); + init_intra_pred2_lsx(TX_8X8, 8x8); + } +} +#undef init_subpel1 +#undef init_subpel2 +#undef init_subpel3 +#undef init_copy +#undef init_fpel +#undef init_intra_pred1_lsx +#undef init_intra_pred2_lsx diff --git a/libavcodec/loongarch/vp9dsp_loongarch.h b/libavcodec/loongarch/vp9dsp_loongarch.h new file mode 100644 index 0000000000..b469326fdc --- /dev/null +++ b/libavcodec/loongarch/vp9dsp_loongarch.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_VP9DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_VP9DSP_LOONGARCH_H + +#define VP9_8TAP_LOONGARCH_LSX_FUNC(SIZE, type, type_idx) \ +void ff_put_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_put_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_put_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); + +#define VP9_COPY_LOONGARCH_LSX_FUNC(SIZE) \ +void ff_copy##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, regular, FILTER_8TAP_REGULAR); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, sharp, FILTER_8TAP_SHARP); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, smooth, FILTER_8TAP_SMOOTH); + +VP9_COPY_LOONGARCH_LSX_FUNC(64); +VP9_COPY_LOONGARCH_LSX_FUNC(32); +VP9_COPY_LOONGARCH_LSX_FUNC(16); +VP9_COPY_LOONGARCH_LSX_FUNC(8); + +#undef VP9_8TAP_LOONGARCH_LSX_FUNC +#undef VP9_COPY_LOONGARCH_LSX_FUNC + +void ff_vert_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_vert_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_hor_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_hor_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_left_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_left_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_left_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_left_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_top_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_top_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_top_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_top_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_128_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_128_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_127_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_127_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_129_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_129_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_tm_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_tm_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_tm_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_tm_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); + +#endif /* AVCODEC_LOONGARCH_VP9DSP_LOONGARCH_H */ diff --git a/libavcodec/vp9dsp.c b/libavcodec/vp9dsp.c index 41b8ad1ad1..82bfe394d1 100644 --- a/libavcodec/vp9dsp.c +++ b/libavcodec/vp9dsp.c @@ -98,4 +98,5 @@ av_cold void ff_vp9dsp_init(VP9DSPContext *dsp, int bpp, int bitexact) if (ARCH_ARM) ff_vp9dsp_init_arm(dsp, bpp); if (ARCH_X86) ff_vp9dsp_init_x86(dsp, bpp, bitexact); if (ARCH_MIPS) ff_vp9dsp_init_mips(dsp, bpp); + if (ARCH_LOONGARCH) ff_vp9dsp_init_loongarch(dsp, bpp); } diff --git a/libavcodec/vp9dsp.h b/libavcodec/vp9dsp.h index e2256316a8..700dd72de8 100644 --- a/libavcodec/vp9dsp.h +++ b/libavcodec/vp9dsp.h @@ -132,5 +132,6 @@ void ff_vp9dsp_init_aarch64(VP9DSPContext *dsp, int bpp); void ff_vp9dsp_init_arm(VP9DSPContext *dsp, int bpp); void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact); void ff_vp9dsp_init_mips(VP9DSPContext *dsp, int bpp); +void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp); #endif /* AVCODEC_VP9DSP_H */ From fea299f8768adbbddcb5b26a34f622a8606945a6 Mon Sep 17 00:00:00 2001 From: Jin Bo Date: Sat, 18 Dec 2021 22:27:56 +0800 Subject: [PATCH 610/894] avcodec: [loongarch] Optimize vp9_lpf/idct with LSX. ffmpeg -i ../10_vp9_1080p_30fps_3Mbps.webm -f rawvideo -y /dev/null -an before:294fps after :567fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 4 +- libavcodec/loongarch/vp9_idct_lsx.c | 1411 ++++++++ libavcodec/loongarch/vp9_lpf_lsx.c | 3141 ++++++++++++++++++ libavcodec/loongarch/vp9dsp_init_loongarch.c | 33 + libavcodec/loongarch/vp9dsp_loongarch.h | 38 + 5 files changed, 4626 insertions(+), 1 deletion(-) create mode 100644 libavcodec/loongarch/vp9_idct_lsx.c create mode 100644 libavcodec/loongarch/vp9_lpf_lsx.c diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 6fcebe40a3..4b83f20e92 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -13,4 +13,6 @@ LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ loongarch/vp8_lpf_lsx.o LSX-OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9_mc_lsx.o \ - loongarch/vp9_intra_lsx.o + loongarch/vp9_intra_lsx.o \ + loongarch/vp9_lpf_lsx.o \ + loongarch/vp9_idct_lsx.o diff --git a/libavcodec/loongarch/vp9_idct_lsx.c b/libavcodec/loongarch/vp9_idct_lsx.c new file mode 100644 index 0000000000..88805814c6 --- /dev/null +++ b/libavcodec/loongarch/vp9_idct_lsx.c @@ -0,0 +1,1411 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Jin Bo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp9dsp_loongarch.h" +#include "libavutil/attributes.h" + +#define VP9_DCT_CONST_BITS 14 +#define ALLOC_ALIGNED(align) __attribute__ ((aligned(align))) +#define ROUND_POWER_OF_TWO(value, n) (((value) + (1 << ((n) - 1))) >> (n)) + +const int32_t cospi_1_64 = 16364; +const int32_t cospi_2_64 = 16305; +const int32_t cospi_3_64 = 16207; +const int32_t cospi_4_64 = 16069; +const int32_t cospi_5_64 = 15893; +const int32_t cospi_6_64 = 15679; +const int32_t cospi_7_64 = 15426; +const int32_t cospi_8_64 = 15137; +const int32_t cospi_9_64 = 14811; +const int32_t cospi_10_64 = 14449; +const int32_t cospi_11_64 = 14053; +const int32_t cospi_12_64 = 13623; +const int32_t cospi_13_64 = 13160; +const int32_t cospi_14_64 = 12665; +const int32_t cospi_15_64 = 12140; +const int32_t cospi_16_64 = 11585; +const int32_t cospi_17_64 = 11003; +const int32_t cospi_18_64 = 10394; +const int32_t cospi_19_64 = 9760; +const int32_t cospi_20_64 = 9102; +const int32_t cospi_21_64 = 8423; +const int32_t cospi_22_64 = 7723; +const int32_t cospi_23_64 = 7005; +const int32_t cospi_24_64 = 6270; +const int32_t cospi_25_64 = 5520; +const int32_t cospi_26_64 = 4756; +const int32_t cospi_27_64 = 3981; +const int32_t cospi_28_64 = 3196; +const int32_t cospi_29_64 = 2404; +const int32_t cospi_30_64 = 1606; +const int32_t cospi_31_64 = 804; + +const int32_t sinpi_1_9 = 5283; +const int32_t sinpi_2_9 = 9929; +const int32_t sinpi_3_9 = 13377; +const int32_t sinpi_4_9 = 15212; + +#define VP9_DOTP_CONST_PAIR(reg0, reg1, cnst0, cnst1, out0, out1) \ +{ \ + __m128i k0_m = __lsx_vreplgr2vr_h(cnst0); \ + __m128i s0_m, s1_m, s2_m, s3_m; \ + \ + s0_m = __lsx_vreplgr2vr_h(cnst1); \ + k0_m = __lsx_vpackev_h(s0_m, k0_m); \ + \ + s1_m = __lsx_vilvl_h(__lsx_vneg_h(reg1), reg0); \ + s0_m = __lsx_vilvh_h(__lsx_vneg_h(reg1), reg0); \ + s3_m = __lsx_vilvl_h(reg0, reg1); \ + s2_m = __lsx_vilvh_h(reg0, reg1); \ + DUP2_ARG2(__lsx_vdp2_w_h, s1_m, k0_m, s0_m, k0_m, s1_m, s0_m); \ + DUP2_ARG2(__lsx_vsrari_w, s1_m, VP9_DCT_CONST_BITS, \ + s0_m, VP9_DCT_CONST_BITS, s1_m, s0_m); \ + out0 = __lsx_vpickev_h(s0_m, s1_m); \ + DUP2_ARG2(__lsx_vdp2_w_h, s3_m, k0_m, s2_m, k0_m, s1_m, s0_m); \ + DUP2_ARG2(__lsx_vsrari_w, s1_m, VP9_DCT_CONST_BITS, \ + s0_m, VP9_DCT_CONST_BITS, s1_m, s0_m); \ + out1 = __lsx_vpickev_h(s0_m, s1_m); \ +} + +#define VP9_SET_COSPI_PAIR(c0_h, c1_h) \ +( { \ + __m128i out0_m, r0_m, r1_m; \ + \ + r0_m = __lsx_vreplgr2vr_h(c0_h); \ + r1_m = __lsx_vreplgr2vr_h(c1_h); \ + out0_m = __lsx_vpackev_h(r1_m, r0_m); \ + \ + out0_m; \ +} ) + +#define VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3) \ +{ \ + uint8_t *dst_m = (uint8_t *) (dst); \ + __m128i dst0_m, dst1_m, dst2_m, dst3_m; \ + __m128i tmp0_m, tmp1_m; \ + __m128i res0_m, res1_m, res2_m, res3_m; \ + __m128i zero_m = __lsx_vldi(0); \ + DUP4_ARG2(__lsx_vld, dst_m, 0, dst_m + dst_stride, 0, \ + dst_m + 2 * dst_stride, 0, dst_m + 3 * dst_stride, 0, \ + dst0_m, dst1_m, dst2_m, dst3_m); \ + DUP4_ARG2(__lsx_vilvl_b, zero_m, dst0_m, zero_m, dst1_m, zero_m, \ + dst2_m, zero_m, dst3_m, res0_m, res1_m, res2_m, res3_m);\ + DUP4_ARG2(__lsx_vadd_h, res0_m, in0, res1_m, in1, res2_m, in2, \ + res3_m, in3, res0_m, res1_m, res2_m, res3_m); \ + DUP4_ARG1(__lsx_vclip255_h, res0_m, res1_m, res2_m, res3_m, \ + res0_m, res1_m, res2_m, res3_m); \ + DUP2_ARG2(__lsx_vpickev_b, res1_m, res0_m, res3_m, res2_m, \ + tmp0_m, tmp1_m); \ + __lsx_vstelm_d(tmp0_m, dst_m, 0, 0); \ + __lsx_vstelm_d(tmp0_m, dst_m + dst_stride, 0, 1); \ + __lsx_vstelm_d(tmp1_m, dst_m + 2 * dst_stride, 0, 0); \ + __lsx_vstelm_d(tmp1_m, dst_m + 3 * dst_stride, 0, 1); \ +} + +#define VP9_UNPCK_UB_SH(in, out_h, out_l) \ +{ \ + __m128i zero = __lsx_vldi(0); \ + out_l = __lsx_vilvl_b(zero, in); \ + out_h = __lsx_vilvh_b(zero, in); \ +} + +#define VP9_ILVLTRANS4x8_H(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3, out4, out5, out6, out7) \ +{ \ + __m128i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + __m128i tmp0_n, tmp1_n, tmp2_n, tmp3_n; \ + __m128i zero_m = __lsx_vldi(0); \ + \ + DUP4_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, in5, in4, in7, in6, \ + tmp0_n, tmp1_n, tmp2_n, tmp3_n); \ + tmp0_m = __lsx_vilvl_w(tmp1_n, tmp0_n); \ + tmp2_m = __lsx_vilvh_w(tmp1_n, tmp0_n); \ + tmp1_m = __lsx_vilvl_w(tmp3_n, tmp2_n); \ + tmp3_m = __lsx_vilvh_w(tmp3_n, tmp2_n); \ + \ + out0 = __lsx_vilvl_d(tmp1_m, tmp0_m); \ + out1 = __lsx_vilvh_d(tmp1_m, tmp0_m); \ + out2 = __lsx_vilvl_d(tmp3_m, tmp2_m); \ + out3 = __lsx_vilvh_d(tmp3_m, tmp2_m); \ + \ + out4 = zero_m; \ + out5 = zero_m; \ + out6 = zero_m; \ + out7 = zero_m; \ +} + +/* multiply and add macro */ +#define VP9_MADD(inp0, inp1, inp2, inp3, cst0, cst1, cst2, cst3, \ + out0, out1, out2, out3) \ +{ \ + __m128i madd_s0_m, madd_s1_m, madd_s2_m, madd_s3_m; \ + __m128i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + \ + madd_s1_m = __lsx_vilvl_h(inp1, inp0); \ + madd_s0_m = __lsx_vilvh_h(inp1, inp0); \ + madd_s3_m = __lsx_vilvl_h(inp3, inp2); \ + madd_s2_m = __lsx_vilvh_h(inp3, inp2); \ + DUP4_ARG2(__lsx_vdp2_w_h, madd_s1_m, cst0, madd_s0_m, cst0, \ + madd_s1_m, cst1, madd_s0_m, cst1, tmp0_m, tmp1_m, \ + tmp2_m, tmp3_m); \ + DUP4_ARG2(__lsx_vsrari_w, tmp0_m, VP9_DCT_CONST_BITS, tmp1_m, \ + VP9_DCT_CONST_BITS, tmp2_m, VP9_DCT_CONST_BITS, tmp3_m, \ + VP9_DCT_CONST_BITS, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP2_ARG2(__lsx_vpickev_h, tmp1_m, tmp0_m, tmp3_m, tmp2_m, out0, out1); \ + DUP4_ARG2(__lsx_vdp2_w_h, madd_s3_m, cst2, madd_s2_m, cst2, madd_s3_m, \ + cst3, madd_s2_m, cst3, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP4_ARG2(__lsx_vsrari_w, tmp0_m, VP9_DCT_CONST_BITS, \ + tmp1_m, VP9_DCT_CONST_BITS, tmp2_m, VP9_DCT_CONST_BITS, \ + tmp3_m, VP9_DCT_CONST_BITS, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP2_ARG2(__lsx_vpickev_h, tmp1_m, tmp0_m, tmp3_m, tmp2_m, out2, out3); \ +} + +#define VP9_SET_CONST_PAIR(mask_h, idx1_h, idx2_h) \ +( { \ + __m128i c0_m, c1_m; \ + \ + DUP2_ARG2(__lsx_vreplvei_h, mask_h, idx1_h, mask_h, idx2_h, c0_m, c1_m); \ + c0_m = __lsx_vpackev_h(c1_m, c0_m); \ + \ + c0_m; \ +} ) + +/* idct 8x8 macro */ +#define VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3, out4, out5, out6, out7) \ +{ \ + __m128i tp0_m, tp1_m, tp2_m, tp3_m, tp4_m, tp5_m, tp6_m, tp7_m; \ + __m128i k0_m, k1_m, k2_m, k3_m, res0_m, res1_m, res2_m, res3_m; \ + __m128i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + v8i16 mask_m = { cospi_28_64, cospi_4_64, cospi_20_64, cospi_12_64, \ + cospi_16_64, -cospi_4_64, -cospi_20_64, -cospi_16_64 }; \ + \ + k0_m = VP9_SET_CONST_PAIR(mask_m, 0, 5); \ + k1_m = VP9_SET_CONST_PAIR(mask_m, 1, 0); \ + k2_m = VP9_SET_CONST_PAIR(mask_m, 6, 3); \ + k3_m = VP9_SET_CONST_PAIR(mask_m, 3, 2); \ + VP9_MADD(in1, in7, in3, in5, k0_m, k1_m, k2_m, k3_m, in1, in7, in3, in5); \ + DUP2_ARG2(__lsx_vsub_h, in1, in3, in7, in5, res0_m, res1_m); \ + k0_m = VP9_SET_CONST_PAIR(mask_m, 4, 7); \ + k1_m = __lsx_vreplvei_h(mask_m, 4); \ + \ + res2_m = __lsx_vilvl_h(res0_m, res1_m); \ + res3_m = __lsx_vilvh_h(res0_m, res1_m); \ + DUP4_ARG2(__lsx_vdp2_w_h, res2_m, k0_m, res3_m, k0_m, res2_m, k1_m, \ + res3_m, k1_m, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP4_ARG2(__lsx_vsrari_w, tmp0_m, VP9_DCT_CONST_BITS, \ + tmp1_m, VP9_DCT_CONST_BITS, tmp2_m, VP9_DCT_CONST_BITS, \ + tmp3_m, VP9_DCT_CONST_BITS, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + tp4_m = __lsx_vadd_h(in1, in3); \ + DUP2_ARG2(__lsx_vpickev_h, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tp5_m, tp6_m); \ + tp7_m = __lsx_vadd_h(in7, in5); \ + k2_m = VP9_SET_COSPI_PAIR(cospi_24_64, -cospi_8_64); \ + k3_m = VP9_SET_COSPI_PAIR(cospi_8_64, cospi_24_64); \ + VP9_MADD(in0, in4, in2, in6, k1_m, k0_m, k2_m, k3_m, \ + in0, in4, in2, in6); \ + LSX_BUTTERFLY_4_H(in0, in4, in2, in6, tp0_m, tp1_m, tp2_m, tp3_m); \ + LSX_BUTTERFLY_8_H(tp0_m, tp1_m, tp2_m, tp3_m, tp4_m, tp5_m, tp6_m, tp7_m, \ + out0, out1, out2, out3, out4, out5, out6, out7); \ +} + +static av_always_inline +void vp9_idct8x8_1_add_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int16_t out; + int32_t val; + __m128i vec; + + out = ROUND_POWER_OF_TWO((input[0] * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO((out * cospi_16_64), VP9_DCT_CONST_BITS); + val = ROUND_POWER_OF_TWO(out, 5); + vec = __lsx_vreplgr2vr_h(val); + input[0] = 0; + + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, vec, vec, vec, vec); + dst += (4 * dst_stride); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, vec, vec, vec, vec); +} + +static void vp9_idct8x8_12_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i s0, s1, s2, s3, s4, s5, s6, s7, k0, k1, k2, k3, m0, m1, m2, m3; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i zero = __lsx_vldi(0); + + /* load vector elements of 8x8 block */ + DUP4_ARG2(__lsx_vld, input, 0, input, 16, input, 32, input, 48, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, input, 64, input, 80, input, 96, input, 112, + in4, in5, in6, in7); + __lsx_vst(zero, input, 0); + __lsx_vst(zero, input, 16); + __lsx_vst(zero, input, 32); + __lsx_vst(zero, input, 48); + __lsx_vst(zero, input, 64); + __lsx_vst(zero, input, 80); + __lsx_vst(zero, input, 96); + __lsx_vst(zero, input, 112); + DUP4_ARG2(__lsx_vilvl_d,in1, in0, in3, in2, in5, in4, in7, + in6, in0, in1, in2, in3); + + /* stage1 */ + DUP2_ARG2(__lsx_vilvh_h, in3, in0, in2, in1, s0, s1); + k0 = VP9_SET_COSPI_PAIR(cospi_28_64, -cospi_4_64); + k1 = VP9_SET_COSPI_PAIR(cospi_4_64, cospi_28_64); + k2 = VP9_SET_COSPI_PAIR(-cospi_20_64, cospi_12_64); + k3 = VP9_SET_COSPI_PAIR(cospi_12_64, cospi_20_64); + DUP4_ARG2(__lsx_vdp2_w_h, s0, k0, s0, k1, s1, k2, s1, k3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsrari_w, tmp0, VP9_DCT_CONST_BITS, tmp1, + VP9_DCT_CONST_BITS, tmp2, VP9_DCT_CONST_BITS, tmp3, + VP9_DCT_CONST_BITS, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vpickev_h, zero, tmp0, zero, tmp1, zero, tmp2, zero, tmp3, + s0, s1, s2, s3); + LSX_BUTTERFLY_4_H(s0, s1, s3, s2, s4, s7, s6, s5); + + /* stage2 */ + DUP2_ARG2(__lsx_vilvl_h, in3, in1, in2, in0, s1, s0); + k0 = VP9_SET_COSPI_PAIR(cospi_16_64, cospi_16_64); + k1 = VP9_SET_COSPI_PAIR(cospi_16_64, -cospi_16_64); + k2 = VP9_SET_COSPI_PAIR(cospi_24_64, -cospi_8_64); + k3 = VP9_SET_COSPI_PAIR(cospi_8_64, cospi_24_64); + DUP4_ARG2(__lsx_vdp2_w_h, s0, k0, s0, k1, s1, k2, s1, k3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsrari_w, tmp0, VP9_DCT_CONST_BITS, tmp1, + VP9_DCT_CONST_BITS, tmp2, VP9_DCT_CONST_BITS, tmp3, + VP9_DCT_CONST_BITS, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vpickev_h, zero, tmp0, zero, tmp1, zero, tmp2, zero, tmp3, + s0, s1, s2, s3); + LSX_BUTTERFLY_4_H(s0, s1, s2, s3, m0, m1, m2, m3); + + /* stage3 */ + s0 = __lsx_vilvl_h(s6, s5); + + k1 = VP9_SET_COSPI_PAIR(-cospi_16_64, cospi_16_64); + DUP2_ARG2(__lsx_vdp2_w_h, s0, k1, s0, k0, tmp0, tmp1); + DUP2_ARG2(__lsx_vsrari_w, tmp0, VP9_DCT_CONST_BITS, tmp1, + VP9_DCT_CONST_BITS, tmp0, tmp1); + DUP2_ARG2(__lsx_vpickev_h, zero, tmp0, zero, tmp1, s2, s3); + + /* stage4 */ + LSX_BUTTERFLY_8_H(m0, m1, m2, m3, s4, s2, s3, s7, + in0, in1, in2, in3, in4, in5, in6, in7); + VP9_ILVLTRANS4x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + + /* final rounding (add 2^4, divide by 2^5) and shift */ + DUP4_ARG2(__lsx_vsrari_h, in0 , 5, in1, 5, in2, 5, in3, 5, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vsrari_h, in4 , 5, in5, 5, in6, 5, in7, 5, + in4, in5, in6, in7); + + /* add block and store 8x8 */ + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3); + dst += (4 * dst_stride); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in4, in5, in6, in7); +} + +static void vp9_idct8x8_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i zero = __lsx_vldi(0); + + /* load vector elements of 8x8 block */ + DUP4_ARG2(__lsx_vld, input, 0, input, 16, input, 32, input, 48, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, input, 64, input, 80, input, 96, input, 112, + in4, in5, in6, in7); + __lsx_vst(zero, input, 0); + __lsx_vst(zero, input, 16); + __lsx_vst(zero, input, 32); + __lsx_vst(zero, input, 48); + __lsx_vst(zero, input, 64); + __lsx_vst(zero, input, 80); + __lsx_vst(zero, input, 96); + __lsx_vst(zero, input, 112); + /* 1D idct8x8 */ + VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + /* columns transform */ + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + /* 1D idct8x8 */ + VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + /* final rounding (add 2^4, divide by 2^5) and shift */ + DUP4_ARG2(__lsx_vsrari_h, in0, 5, in1, 5, in2, 5, in3, 5, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vsrari_h, in4, 5, in5, 5, in6, 5, in7, 5, + in4, in5, in6, in7); + /* add block and store 8x8 */ + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3); + dst += (4 * dst_stride); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in4, in5, in6, in7); +} + +static void vp9_idct16_1d_columns_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + __m128i loc0, loc1, loc2, loc3; + __m128i reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14; + __m128i reg1, reg3, reg5, reg7, reg9, reg11, reg13, reg15; + __m128i tmp5, tmp6, tmp7; + __m128i zero = __lsx_vldi(0); + int32_t offset = dst_stride << 2; + + DUP4_ARG2(__lsx_vld, input, 32*0, input, 32*1, input, 32*2, input, 32*3, + reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, input, 32*4, input, 32*5, input, 32*6, input, 32*7, + reg4, reg5, reg6, reg7); + DUP4_ARG2(__lsx_vld, input, 32*8, input, 32*9, input, 32*10, input, 32*11, + reg8, reg9, reg10, reg11); + DUP4_ARG2(__lsx_vld, input, 32*12, input, 32*13, input, 32*14, input, + 32*15, reg12, reg13, reg14, reg15); + + __lsx_vst(zero, input, 32*0); + __lsx_vst(zero, input, 32*1); + __lsx_vst(zero, input, 32*2); + __lsx_vst(zero, input, 32*3); + __lsx_vst(zero, input, 32*4); + __lsx_vst(zero, input, 32*5); + __lsx_vst(zero, input, 32*6); + __lsx_vst(zero, input, 32*7); + __lsx_vst(zero, input, 32*8); + __lsx_vst(zero, input, 32*9); + __lsx_vst(zero, input, 32*10); + __lsx_vst(zero, input, 32*11); + __lsx_vst(zero, input, 32*12); + __lsx_vst(zero, input, 32*13); + __lsx_vst(zero, input, 32*14); + __lsx_vst(zero, input, 32*15); + + VP9_DOTP_CONST_PAIR(reg2, reg14, cospi_28_64, cospi_4_64, reg2, reg14); + VP9_DOTP_CONST_PAIR(reg10, reg6, cospi_12_64, cospi_20_64, reg10, reg6); + LSX_BUTTERFLY_4_H(reg2, reg14, reg6, reg10, loc0, loc1, reg14, reg2); + VP9_DOTP_CONST_PAIR(reg14, reg2, cospi_16_64, cospi_16_64, loc2, loc3); + VP9_DOTP_CONST_PAIR(reg0, reg8, cospi_16_64, cospi_16_64, reg0, reg8); + VP9_DOTP_CONST_PAIR(reg4, reg12, cospi_24_64, cospi_8_64, reg4, reg12); + LSX_BUTTERFLY_4_H(reg8, reg0, reg4, reg12, reg2, reg6, reg10, reg14); + + reg0 = __lsx_vsub_h(reg2, loc1); + reg2 = __lsx_vadd_h(reg2, loc1); + reg12 = __lsx_vsub_h(reg14, loc0); + reg14 = __lsx_vadd_h(reg14, loc0); + reg4 = __lsx_vsub_h(reg6, loc3); + reg6 = __lsx_vadd_h(reg6, loc3); + reg8 = __lsx_vsub_h(reg10, loc2); + reg10 = __lsx_vadd_h(reg10, loc2); + + /* stage2 */ + VP9_DOTP_CONST_PAIR(reg1, reg15, cospi_30_64, cospi_2_64, reg1, reg15); + VP9_DOTP_CONST_PAIR(reg9, reg7, cospi_14_64, cospi_18_64, loc2, loc3); + + reg9 = __lsx_vsub_h(reg1, loc2); + reg1 = __lsx_vadd_h(reg1, loc2); + reg7 = __lsx_vsub_h(reg15, loc3); + reg15 = __lsx_vadd_h(reg15, loc3); + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_22_64, cospi_10_64, reg5, reg11); + VP9_DOTP_CONST_PAIR(reg13, reg3, cospi_6_64, cospi_26_64, loc0, loc1); + LSX_BUTTERFLY_4_H(loc0, loc1, reg11, reg5, reg13, reg3, reg11, reg5); + + loc1 = __lsx_vadd_h(reg15, reg3); + reg3 = __lsx_vsub_h(reg15, reg3); + loc2 = __lsx_vadd_h(reg2, loc1); + reg15 = __lsx_vsub_h(reg2, loc1); + + loc1 = __lsx_vadd_h(reg1, reg13); + reg13 = __lsx_vsub_h(reg1, reg13); + loc0 = __lsx_vadd_h(reg0, loc1); + loc1 = __lsx_vsub_h(reg0, loc1); + tmp6 = loc0; + tmp7 = loc1; + reg0 = loc2; + + VP9_DOTP_CONST_PAIR(reg7, reg9, cospi_24_64, cospi_8_64, reg7, reg9); + VP9_DOTP_CONST_PAIR(__lsx_vneg_h(reg5), __lsx_vneg_h(reg11), cospi_8_64, + cospi_24_64, reg5, reg11); + + loc0 = __lsx_vadd_h(reg9, reg5); + reg5 = __lsx_vsub_h(reg9, reg5); + reg2 = __lsx_vadd_h(reg6, loc0); + reg1 = __lsx_vsub_h(reg6, loc0); + + loc0 = __lsx_vadd_h(reg7, reg11); + reg11 = __lsx_vsub_h(reg7, reg11); + loc1 = __lsx_vadd_h(reg4, loc0); + loc2 = __lsx_vsub_h(reg4, loc0); + tmp5 = loc1; + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_16_64, cospi_16_64, reg5, reg11); + LSX_BUTTERFLY_4_H(reg8, reg10, reg11, reg5, loc0, reg4, reg9, loc1); + + reg10 = loc0; + reg11 = loc1; + + VP9_DOTP_CONST_PAIR(reg3, reg13, cospi_16_64, cospi_16_64, reg3, reg13); + LSX_BUTTERFLY_4_H(reg12, reg14, reg13, reg3, reg8, reg6, reg7, reg5); + reg13 = loc2; + + /* Transpose and store the output */ + reg12 = tmp5; + reg14 = tmp6; + reg3 = tmp7; + + DUP4_ARG2(__lsx_vsrari_h, reg0, 6, reg2, 6, reg4, 6, reg6, 6, + reg0, reg2, reg4, reg6); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg0, reg2, reg4, reg6); + dst += offset; + DUP4_ARG2(__lsx_vsrari_h, reg8, 6, reg10, 6, reg12, 6, reg14, 6, + reg8, reg10, reg12, reg14); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg8, reg10, reg12, reg14); + dst += offset; + DUP4_ARG2(__lsx_vsrari_h, reg3, 6, reg5, 6, reg11, 6, reg13, 6, + reg3, reg5, reg11, reg13); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg3, reg13, reg11, reg5); + dst += offset; + DUP4_ARG2(__lsx_vsrari_h, reg1, 6, reg7, 6, reg9, 6, reg15, 6, + reg1, reg7, reg9, reg15); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg7, reg9, reg1, reg15); +} + +static void vp9_idct16_1d_columns_lsx(int16_t *input, int16_t *output) +{ + __m128i loc0, loc1, loc2, loc3; + __m128i reg1, reg3, reg5, reg7, reg9, reg11, reg13, reg15; + __m128i reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14; + __m128i tmp5, tmp6, tmp7; + __m128i zero = __lsx_vldi(0); + int16_t *offset; + + DUP4_ARG2(__lsx_vld, input, 32*0, input, 32*1, input, 32*2, input, 32*3, + reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, input, 32*4, input, 32*5, input, 32*6, input, 32*7, + reg4, reg5, reg6, reg7); + DUP4_ARG2(__lsx_vld, input, 32*8, input, 32*9, input, 32*10, input, 32*11, + reg8, reg9, reg10, reg11); + DUP4_ARG2(__lsx_vld, input, 32*12, input, 32*13, input, 32*14, input, + 32*15, reg12, reg13, reg14, reg15); + + __lsx_vst(zero, input, 32*0); + __lsx_vst(zero, input, 32*1); + __lsx_vst(zero, input, 32*2); + __lsx_vst(zero, input, 32*3); + __lsx_vst(zero, input, 32*4); + __lsx_vst(zero, input, 32*5); + __lsx_vst(zero, input, 32*6); + __lsx_vst(zero, input, 32*7); + __lsx_vst(zero, input, 32*8); + __lsx_vst(zero, input, 32*9); + __lsx_vst(zero, input, 32*10); + __lsx_vst(zero, input, 32*11); + __lsx_vst(zero, input, 32*12); + __lsx_vst(zero, input, 32*13); + __lsx_vst(zero, input, 32*14); + __lsx_vst(zero, input, 32*15); + + VP9_DOTP_CONST_PAIR(reg2, reg14, cospi_28_64, cospi_4_64, reg2, reg14); + VP9_DOTP_CONST_PAIR(reg10, reg6, cospi_12_64, cospi_20_64, reg10, reg6); + LSX_BUTTERFLY_4_H(reg2, reg14, reg6, reg10, loc0, loc1, reg14, reg2); + VP9_DOTP_CONST_PAIR(reg14, reg2, cospi_16_64, cospi_16_64, loc2, loc3); + VP9_DOTP_CONST_PAIR(reg0, reg8, cospi_16_64, cospi_16_64, reg0, reg8); + VP9_DOTP_CONST_PAIR(reg4, reg12, cospi_24_64, cospi_8_64, reg4, reg12); + LSX_BUTTERFLY_4_H(reg8, reg0, reg4, reg12, reg2, reg6, reg10, reg14); + + reg0 = __lsx_vsub_h(reg2, loc1); + reg2 = __lsx_vadd_h(reg2, loc1); + reg12 = __lsx_vsub_h(reg14, loc0); + reg14 = __lsx_vadd_h(reg14, loc0); + reg4 = __lsx_vsub_h(reg6, loc3); + reg6 = __lsx_vadd_h(reg6, loc3); + reg8 = __lsx_vsub_h(reg10, loc2); + reg10 = __lsx_vadd_h(reg10, loc2); + + /* stage2 */ + VP9_DOTP_CONST_PAIR(reg1, reg15, cospi_30_64, cospi_2_64, reg1, reg15); + VP9_DOTP_CONST_PAIR(reg9, reg7, cospi_14_64, cospi_18_64, loc2, loc3); + + reg9 = __lsx_vsub_h(reg1, loc2); + reg1 = __lsx_vadd_h(reg1, loc2); + reg7 = __lsx_vsub_h(reg15, loc3); + reg15 = __lsx_vadd_h(reg15, loc3); + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_22_64, cospi_10_64, reg5, reg11); + VP9_DOTP_CONST_PAIR(reg13, reg3, cospi_6_64, cospi_26_64, loc0, loc1); + LSX_BUTTERFLY_4_H(loc0, loc1, reg11, reg5, reg13, reg3, reg11, reg5); + + loc1 = __lsx_vadd_h(reg15, reg3); + reg3 = __lsx_vsub_h(reg15, reg3); + loc2 = __lsx_vadd_h(reg2, loc1); + reg15 = __lsx_vsub_h(reg2, loc1); + + loc1 = __lsx_vadd_h(reg1, reg13); + reg13 = __lsx_vsub_h(reg1, reg13); + loc0 = __lsx_vadd_h(reg0, loc1); + loc1 = __lsx_vsub_h(reg0, loc1); + tmp6 = loc0; + tmp7 = loc1; + reg0 = loc2; + + VP9_DOTP_CONST_PAIR(reg7, reg9, cospi_24_64, cospi_8_64, reg7, reg9); + VP9_DOTP_CONST_PAIR(__lsx_vneg_h(reg5), __lsx_vneg_h(reg11), cospi_8_64, + cospi_24_64, reg5, reg11); + + loc0 = __lsx_vadd_h(reg9, reg5); + reg5 = __lsx_vsub_h(reg9, reg5); + reg2 = __lsx_vadd_h(reg6, loc0); + reg1 = __lsx_vsub_h(reg6, loc0); + + loc0 = __lsx_vadd_h(reg7, reg11); + reg11 = __lsx_vsub_h(reg7, reg11); + loc1 = __lsx_vadd_h(reg4, loc0); + loc2 = __lsx_vsub_h(reg4, loc0); + + tmp5 = loc1; + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_16_64, cospi_16_64, reg5, reg11); + LSX_BUTTERFLY_4_H(reg8, reg10, reg11, reg5, loc0, reg4, reg9, loc1); + + reg10 = loc0; + reg11 = loc1; + + VP9_DOTP_CONST_PAIR(reg3, reg13, cospi_16_64, cospi_16_64, reg3, reg13); + LSX_BUTTERFLY_4_H(reg12, reg14, reg13, reg3, reg8, reg6, reg7, reg5); + reg13 = loc2; + + /* Transpose and store the output */ + reg12 = tmp5; + reg14 = tmp6; + reg3 = tmp7; + + /* transpose block */ + LSX_TRANSPOSE8x8_H(reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14, + reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14); + + __lsx_vst(reg0, output, 32*0); + __lsx_vst(reg2, output, 32*1); + __lsx_vst(reg4, output, 32*2); + __lsx_vst(reg6, output, 32*3); + __lsx_vst(reg8, output, 32*4); + __lsx_vst(reg10, output, 32*5); + __lsx_vst(reg12, output, 32*6); + __lsx_vst(reg14, output, 32*7); + + /* transpose block */ + LSX_TRANSPOSE8x8_H(reg3, reg13, reg11, reg5, reg7, reg9, reg1, reg15, + reg3, reg13, reg11, reg5, reg7, reg9, reg1, reg15); + + offset = output + 8; + __lsx_vst(reg3, offset, 32*0); + __lsx_vst(reg13, offset, 32*1); + __lsx_vst(reg11, offset, 32*2); + __lsx_vst(reg5, offset, 32*3); + + offset = output + 8 + 4 * 16; + __lsx_vst(reg7, offset, 32*0); + __lsx_vst(reg9, offset, 32*1); + __lsx_vst(reg1, offset, 32*2); + __lsx_vst(reg15, offset, 32*3); +} + +static void vp9_idct16x16_1_add_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + uint8_t i; + int16_t out; + __m128i vec, res0, res1, res2, res3, res4, res5, res6, res7; + __m128i dst0, dst1, dst2, dst3, tmp0, tmp1, tmp2, tmp3; + int32_t stride2 = dst_stride << 1; + int32_t stride3 = stride2 + dst_stride; + int32_t stride4 = stride2 << 1; + + out = ROUND_POWER_OF_TWO((input[0] * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO((out * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO(out, 6); + input[0] = 0; + vec = __lsx_vreplgr2vr_h(out); + + for (i = 4; i--;) { + dst0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, stride2, dst1, dst2); + dst3 = __lsx_vldx(dst, stride3); + VP9_UNPCK_UB_SH(dst0, res4, res0); + VP9_UNPCK_UB_SH(dst1, res5, res1); + VP9_UNPCK_UB_SH(dst2, res6, res2); + VP9_UNPCK_UB_SH(dst3, res7, res3); + DUP4_ARG2(__lsx_vadd_h, res0, vec, res1, vec, res2, vec, res3, vec, + res0, res1, res2, res3); + DUP4_ARG2(__lsx_vadd_h, res4, vec, res5, vec, res6, vec, res7, vec, + res4, res5, res6, res7); + DUP4_ARG1(__lsx_vclip255_h, res0, res1, res2, res3, + res0, res1, res2, res3); + DUP4_ARG1(__lsx_vclip255_h, res4, res5, res6, res7, + res4, res5, res6, res7); + DUP4_ARG2(__lsx_vpickev_b, res4, res0, res5, res1, res6, + res2, res7, res3, tmp0, tmp1, tmp2, tmp3); + __lsx_vst(tmp0, dst, 0); + __lsx_vstx(tmp1, dst, dst_stride); + __lsx_vstx(tmp2, dst, stride2); + __lsx_vstx(tmp3, dst, stride3); + dst += stride4; + } +} + +static void vp9_idct16x16_10_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[16 * 16] ALLOC_ALIGNED(16); + int16_t *out = out_arr; + __m128i zero = __lsx_vldi(0); + + /* transform rows */ + vp9_idct16_1d_columns_lsx(input, out); + + /* short case just considers top 4 rows as valid output */ + out += 4 * 16; + for (i = 3; i--;) { + __lsx_vst(zero, out, 0); + __lsx_vst(zero, out, 16); + __lsx_vst(zero, out, 32); + __lsx_vst(zero, out, 48); + __lsx_vst(zero, out, 64); + __lsx_vst(zero, out, 80); + __lsx_vst(zero, out, 96); + __lsx_vst(zero, out, 112); + out += 64; + } + + out = out_arr; + + /* transform columns */ + for (i = 0; i < 2; i++) { + /* process 8 * 16 block */ + vp9_idct16_1d_columns_addblk_lsx((out + (i << 3)), (dst + (i << 3)), + dst_stride); + } +} + +static void vp9_idct16x16_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[16 * 16] ALLOC_ALIGNED(16); + int16_t *out = out_arr; + + /* transform rows */ + for (i = 0; i < 2; i++) { + /* process 8 * 16 block */ + vp9_idct16_1d_columns_lsx((input + (i << 3)), (out + (i << 7))); + } + + /* transform columns */ + for (i = 0; i < 2; i++) { + /* process 8 * 16 block */ + vp9_idct16_1d_columns_addblk_lsx((out + (i << 3)), (dst + (i << 3)), + dst_stride); + } +} + +static void vp9_idct_butterfly_transpose_store(int16_t *tmp_buf, + int16_t *tmp_eve_buf, + int16_t *tmp_odd_buf, + int16_t *dst) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i m0, m1, m2, m3, m4, m5, m6, m7, n0, n1, n2, n3, n4, n5, n6, n7; + + /* FINAL BUTTERFLY : Dependency on Even & Odd */ + vec0 = __lsx_vld(tmp_odd_buf, 0); + vec1 = __lsx_vld(tmp_odd_buf, 9 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 14 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 6 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 0); + loc1 = __lsx_vld(tmp_eve_buf, 8 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 4 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 12 * 16); + + DUP4_ARG2(__lsx_vadd_h,loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m0, m4, m2, m6); + + #define SUB(a, b) __lsx_vsub_h(a, b) + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 31 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 23 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 27 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 19 * 16); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 4 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 13 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 10 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 3 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 2 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 10 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 6 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 14 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m1, m5, m3, m7); + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 29 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 21 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 25 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 17 * 16); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 2 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 11 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 12 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 7 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 1 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 9 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 5 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 13 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n0, n4, n2, n6); + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 30 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 22 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 26 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 18 * 16); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 5 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 15 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 8 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 1 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 3 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 11 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 7 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 15 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n1, n5, n3, n7); + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 28 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 20 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 24 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 16 * 16); + + /* Transpose : 16 vectors */ + /* 1st & 2nd 8x8 */ + LSX_TRANSPOSE8x8_H(m0, n0, m1, n1, m2, n2, m3, n3, + m0, n0, m1, n1, m2, n2, m3, n3); + __lsx_vst(m0, dst, 0); + __lsx_vst(n0, dst, 32 * 2); + __lsx_vst(m1, dst, 32 * 4); + __lsx_vst(n1, dst, 32 * 6); + __lsx_vst(m2, dst, 32 * 8); + __lsx_vst(n2, dst, 32 * 10); + __lsx_vst(m3, dst, 32 * 12); + __lsx_vst(n3, dst, 32 * 14); + + LSX_TRANSPOSE8x8_H(m4, n4, m5, n5, m6, n6, m7, n7, + m4, n4, m5, n5, m6, n6, m7, n7); + + __lsx_vst(m4, dst, 16); + __lsx_vst(n4, dst, 16 + 32 * 2); + __lsx_vst(m5, dst, 16 + 32 * 4); + __lsx_vst(n5, dst, 16 + 32 * 6); + __lsx_vst(m6, dst, 16 + 32 * 8); + __lsx_vst(n6, dst, 16 + 32 * 10); + __lsx_vst(m7, dst, 16 + 32 * 12); + __lsx_vst(n7, dst, 16 + 32 * 14); + + /* 3rd & 4th 8x8 */ + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 16, tmp_buf, 16 * 17, + tmp_buf, 16 * 18, tmp_buf, 16 * 19, m0, n0, m1, n1); + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 20, tmp_buf, 16 * 21, + tmp_buf, 16 * 22, tmp_buf, 16 * 23, m2, n2, m3, n3); + + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 24, tmp_buf, 16 * 25, + tmp_buf, 16 * 26, tmp_buf, 16 * 27, m4, n4, m5, n5); + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 28, tmp_buf, 16 * 29, + tmp_buf, 16 * 30, tmp_buf, 16 * 31, m6, n6, m7, n7); + + LSX_TRANSPOSE8x8_H(m0, n0, m1, n1, m2, n2, m3, n3, + m0, n0, m1, n1, m2, n2, m3, n3); + + __lsx_vst(m0, dst, 32); + __lsx_vst(n0, dst, 32 + 32 * 2); + __lsx_vst(m1, dst, 32 + 32 * 4); + __lsx_vst(n1, dst, 32 + 32 * 6); + __lsx_vst(m2, dst, 32 + 32 * 8); + __lsx_vst(n2, dst, 32 + 32 * 10); + __lsx_vst(m3, dst, 32 + 32 * 12); + __lsx_vst(n3, dst, 32 + 32 * 14); + + LSX_TRANSPOSE8x8_H(m4, n4, m5, n5, m6, n6, m7, n7, + m4, n4, m5, n5, m6, n6, m7, n7); + + __lsx_vst(m4, dst, 48); + __lsx_vst(n4, dst, 48 + 32 * 2); + __lsx_vst(m5, dst, 48 + 32 * 4); + __lsx_vst(n5, dst, 48 + 32 * 6); + __lsx_vst(m6, dst, 48 + 32 * 8); + __lsx_vst(n6, dst, 48 + 32 * 10); + __lsx_vst(m7, dst, 48 + 32 * 12); + __lsx_vst(n7, dst, 48 + 32 * 14); +} + +static void vp9_idct8x32_column_even_process_store(int16_t *tmp_buf, + int16_t *tmp_eve_buf) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; + __m128i stp0, stp1, stp2, stp3, stp4, stp5, stp6, stp7; + __m128i zero = __lsx_vldi(0); + + /* Even stage 1 */ + DUP4_ARG2(__lsx_vld, tmp_buf, 0, tmp_buf, 32 * 8, + tmp_buf, 32 * 16, tmp_buf, 32 * 24, reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, tmp_buf, 32 * 32, tmp_buf, 32 * 40, + tmp_buf, 32 * 48, tmp_buf, 32 * 56, reg4, reg5, reg6, reg7); + + __lsx_vst(zero, tmp_buf, 0); + __lsx_vst(zero, tmp_buf, 32 * 8); + __lsx_vst(zero, tmp_buf, 32 * 16); + __lsx_vst(zero, tmp_buf, 32 * 24); + __lsx_vst(zero, tmp_buf, 32 * 32); + __lsx_vst(zero, tmp_buf, 32 * 40); + __lsx_vst(zero, tmp_buf, 32 * 48); + __lsx_vst(zero, tmp_buf, 32 * 56); + + tmp_buf += (2 * 32); + + VP9_DOTP_CONST_PAIR(reg1, reg7, cospi_28_64, cospi_4_64, reg1, reg7); + VP9_DOTP_CONST_PAIR(reg5, reg3, cospi_12_64, cospi_20_64, reg5, reg3); + LSX_BUTTERFLY_4_H(reg1, reg7, reg3, reg5, vec1, vec3, vec2, vec0); + VP9_DOTP_CONST_PAIR(vec2, vec0, cospi_16_64, cospi_16_64, loc2, loc3); + + loc1 = vec3; + loc0 = vec1; + + VP9_DOTP_CONST_PAIR(reg0, reg4, cospi_16_64, cospi_16_64, reg0, reg4); + VP9_DOTP_CONST_PAIR(reg2, reg6, cospi_24_64, cospi_8_64, reg2, reg6); + LSX_BUTTERFLY_4_H(reg4, reg0, reg2, reg6, vec1, vec3, vec2, vec0); + LSX_BUTTERFLY_4_H(vec0, vec1, loc1, loc0, stp3, stp0, stp7, stp4); + LSX_BUTTERFLY_4_H(vec2, vec3, loc3, loc2, stp2, stp1, stp6, stp5); + + /* Even stage 2 */ + /* Load 8 */ + DUP4_ARG2(__lsx_vld, tmp_buf, 0, tmp_buf, 32 * 8, + tmp_buf, 32 * 16, tmp_buf, 32 * 24, reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, tmp_buf, 32 * 32, tmp_buf, 32 * 40, + tmp_buf, 32 * 48, tmp_buf, 32 * 56, reg4, reg5, reg6, reg7); + + __lsx_vst(zero, tmp_buf, 0); + __lsx_vst(zero, tmp_buf, 32 * 8); + __lsx_vst(zero, tmp_buf, 32 * 16); + __lsx_vst(zero, tmp_buf, 32 * 24); + __lsx_vst(zero, tmp_buf, 32 * 32); + __lsx_vst(zero, tmp_buf, 32 * 40); + __lsx_vst(zero, tmp_buf, 32 * 48); + __lsx_vst(zero, tmp_buf, 32 * 56); + + VP9_DOTP_CONST_PAIR(reg0, reg7, cospi_30_64, cospi_2_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(reg4, reg3, cospi_14_64, cospi_18_64, reg4, reg3); + VP9_DOTP_CONST_PAIR(reg2, reg5, cospi_22_64, cospi_10_64, reg2, reg5); + VP9_DOTP_CONST_PAIR(reg6, reg1, cospi_6_64, cospi_26_64, reg6, reg1); + + vec0 = __lsx_vadd_h(reg0, reg4); + reg0 = __lsx_vsub_h(reg0, reg4); + reg4 = __lsx_vadd_h(reg6, reg2); + reg6 = __lsx_vsub_h(reg6, reg2); + reg2 = __lsx_vadd_h(reg1, reg5); + reg1 = __lsx_vsub_h(reg1, reg5); + reg5 = __lsx_vadd_h(reg7, reg3); + reg7 = __lsx_vsub_h(reg7, reg3); + reg3 = vec0; + + vec1 = reg2; + reg2 = __lsx_vadd_h(reg3, reg4); + reg3 = __lsx_vsub_h(reg3, reg4); + reg4 = __lsx_vsub_h(reg5, vec1); + reg5 = __lsx_vadd_h(reg5, vec1); + + VP9_DOTP_CONST_PAIR(reg7, reg0, cospi_24_64, cospi_8_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(__lsx_vneg_h(reg6), reg1, cospi_24_64, cospi_8_64, + reg6, reg1); + + vec0 = __lsx_vsub_h(reg0, reg6); + reg0 = __lsx_vadd_h(reg0, reg6); + vec1 = __lsx_vsub_h(reg7, reg1); + reg7 = __lsx_vadd_h(reg7, reg1); + + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, reg6, reg1); + VP9_DOTP_CONST_PAIR(reg4, reg3, cospi_16_64, cospi_16_64, reg3, reg4); + + /* Even stage 3 : Dependency on Even stage 1 & Even stage 2 */ + /* Store 8 */ + LSX_BUTTERFLY_4_H(stp0, stp1, reg7, reg5, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 0); + __lsx_vst(loc3, tmp_eve_buf, 16); + __lsx_vst(loc2, tmp_eve_buf, 14 * 16); + __lsx_vst(loc0, tmp_eve_buf, 14 * 16 + 16); + LSX_BUTTERFLY_4_H(stp2, stp3, reg4, reg1, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 2 * 16); + __lsx_vst(loc3, tmp_eve_buf, 2 * 16 + 16); + __lsx_vst(loc2, tmp_eve_buf, 12 * 16); + __lsx_vst(loc0, tmp_eve_buf, 12 * 16 + 16); + + /* Store 8 */ + LSX_BUTTERFLY_4_H(stp4, stp5, reg6, reg3, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 4 * 16); + __lsx_vst(loc3, tmp_eve_buf, 4 * 16 + 16); + __lsx_vst(loc2, tmp_eve_buf, 10 * 16); + __lsx_vst(loc0, tmp_eve_buf, 10 * 16 + 16); + + LSX_BUTTERFLY_4_H(stp6, stp7, reg2, reg0, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 6 * 16); + __lsx_vst(loc3, tmp_eve_buf, 6 * 16 + 16); + __lsx_vst(loc2, tmp_eve_buf, 8 * 16); + __lsx_vst(loc0, tmp_eve_buf, 8 * 16 + 16); +} + +static void vp9_idct8x32_column_odd_process_store(int16_t *tmp_buf, + int16_t *tmp_odd_buf) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; + __m128i zero = __lsx_vldi(0); + + /* Odd stage 1 */ + reg0 = __lsx_vld(tmp_buf, 64); + reg1 = __lsx_vld(tmp_buf, 7 * 64); + reg2 = __lsx_vld(tmp_buf, 9 * 64); + reg3 = __lsx_vld(tmp_buf, 15 * 64); + reg4 = __lsx_vld(tmp_buf, 17 * 64); + reg5 = __lsx_vld(tmp_buf, 23 * 64); + reg6 = __lsx_vld(tmp_buf, 25 * 64); + reg7 = __lsx_vld(tmp_buf, 31 * 64); + + __lsx_vst(zero, tmp_buf, 64); + __lsx_vst(zero, tmp_buf, 7 * 64); + __lsx_vst(zero, tmp_buf, 9 * 64); + __lsx_vst(zero, tmp_buf, 15 * 64); + __lsx_vst(zero, tmp_buf, 17 * 64); + __lsx_vst(zero, tmp_buf, 23 * 64); + __lsx_vst(zero, tmp_buf, 25 * 64); + __lsx_vst(zero, tmp_buf, 31 * 64); + + VP9_DOTP_CONST_PAIR(reg0, reg7, cospi_31_64, cospi_1_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(reg4, reg3, cospi_15_64, cospi_17_64, reg3, reg4); + VP9_DOTP_CONST_PAIR(reg2, reg5, cospi_23_64, cospi_9_64, reg2, reg5); + VP9_DOTP_CONST_PAIR(reg6, reg1, cospi_7_64, cospi_25_64, reg1, reg6); + + vec0 = __lsx_vadd_h(reg0, reg3); + reg0 = __lsx_vsub_h(reg0, reg3); + reg3 = __lsx_vadd_h(reg7, reg4); + reg7 = __lsx_vsub_h(reg7, reg4); + reg4 = __lsx_vadd_h(reg1, reg2); + reg1 = __lsx_vsub_h(reg1, reg2); + reg2 = __lsx_vadd_h(reg6, reg5); + reg6 = __lsx_vsub_h(reg6, reg5); + reg5 = vec0; + + /* 4 Stores */ + DUP2_ARG2(__lsx_vadd_h, reg5, reg4, reg3, reg2, vec0, vec1); + __lsx_vst(vec0, tmp_odd_buf, 4 * 16); + __lsx_vst(vec1, tmp_odd_buf, 4 * 16 + 16); + DUP2_ARG2(__lsx_vsub_h, reg5, reg4, reg3, reg2, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_24_64, cospi_8_64, vec0, vec1); + __lsx_vst(vec0, tmp_odd_buf, 0); + __lsx_vst(vec1, tmp_odd_buf, 16); + + /* 4 Stores */ + VP9_DOTP_CONST_PAIR(reg7, reg0, cospi_28_64, cospi_4_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(reg6, reg1, -cospi_4_64, cospi_28_64, reg1, reg6); + LSX_BUTTERFLY_4_H(reg0, reg7, reg6, reg1, vec0, vec1, vec2, vec3); + __lsx_vst(vec0, tmp_odd_buf, 6 * 16); + __lsx_vst(vec1, tmp_odd_buf, 6 * 16 + 16); + VP9_DOTP_CONST_PAIR(vec2, vec3, cospi_24_64, cospi_8_64, vec2, vec3); + __lsx_vst(vec2, tmp_odd_buf, 2 * 16); + __lsx_vst(vec3, tmp_odd_buf, 2 * 16 + 16); + + /* Odd stage 2 */ + /* 8 loads */ + reg0 = __lsx_vld(tmp_buf, 3 * 64); + reg1 = __lsx_vld(tmp_buf, 5 * 64); + reg2 = __lsx_vld(tmp_buf, 11 * 64); + reg3 = __lsx_vld(tmp_buf, 13 * 64); + reg4 = __lsx_vld(tmp_buf, 19 * 64); + reg5 = __lsx_vld(tmp_buf, 21 * 64); + reg6 = __lsx_vld(tmp_buf, 27 * 64); + reg7 = __lsx_vld(tmp_buf, 29 * 64); + + __lsx_vst(zero, tmp_buf, 3 * 64); + __lsx_vst(zero, tmp_buf, 5 * 64); + __lsx_vst(zero, tmp_buf, 11 * 64); + __lsx_vst(zero, tmp_buf, 13 * 64); + __lsx_vst(zero, tmp_buf, 19 * 64); + __lsx_vst(zero, tmp_buf, 21 * 64); + __lsx_vst(zero, tmp_buf, 27 * 64); + __lsx_vst(zero, tmp_buf, 29 * 64); + + VP9_DOTP_CONST_PAIR(reg1, reg6, cospi_27_64, cospi_5_64, reg1, reg6); + VP9_DOTP_CONST_PAIR(reg5, reg2, cospi_11_64, cospi_21_64, reg2, reg5); + VP9_DOTP_CONST_PAIR(reg3, reg4, cospi_19_64, cospi_13_64, reg3, reg4); + VP9_DOTP_CONST_PAIR(reg7, reg0, cospi_3_64, cospi_29_64, reg0, reg7); + + /* 4 Stores */ + DUP4_ARG2(__lsx_vsub_h,reg1, reg2, reg6, reg5, reg0, reg3, reg7, reg4, + vec0, vec1, vec2, vec3); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_12_64, cospi_20_64, loc0, loc1); + VP9_DOTP_CONST_PAIR(vec3, vec2, -cospi_20_64, cospi_12_64, loc2, loc3); + LSX_BUTTERFLY_4_H(loc2, loc3, loc1, loc0, vec0, vec1, vec3, vec2); + __lsx_vst(vec0, tmp_odd_buf, 12 * 16); + __lsx_vst(vec1, tmp_odd_buf, 12 * 16 + 3 * 16); + VP9_DOTP_CONST_PAIR(vec3, vec2, -cospi_8_64, cospi_24_64, vec0, vec1); + __lsx_vst(vec0, tmp_odd_buf, 10 * 16); + __lsx_vst(vec1, tmp_odd_buf, 10 * 16 + 16); + + /* 4 Stores */ + DUP4_ARG2(__lsx_vadd_h, reg0, reg3, reg1, reg2, reg5, reg6, reg4, reg7, + vec0, vec1, vec2, vec3); + LSX_BUTTERFLY_4_H(vec0, vec3, vec2, vec1, reg0, reg1, reg3, reg2); + __lsx_vst(reg0, tmp_odd_buf, 13 * 16); + __lsx_vst(reg1, tmp_odd_buf, 13 * 16 + 16); + VP9_DOTP_CONST_PAIR(reg3, reg2, -cospi_8_64, cospi_24_64, + reg0, reg1); + __lsx_vst(reg0, tmp_odd_buf, 8 * 16); + __lsx_vst(reg1, tmp_odd_buf, 8 * 16 + 16); + + /* Odd stage 3 : Dependency on Odd stage 1 & Odd stage 2 */ + /* Load 8 & Store 8 */ + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 0, tmp_odd_buf, 16, + tmp_odd_buf, 32, tmp_odd_buf, 48, reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 8 * 16, tmp_odd_buf, 8 * 16 + 16, + tmp_odd_buf, 8 * 16 + 32, tmp_odd_buf, 8 * 16 + 48, + reg4, reg5, reg6, reg7); + + DUP4_ARG2(__lsx_vadd_h, reg0, reg4, reg1, reg5, reg2, reg6, reg3, reg7, + loc0, loc1, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 0); + __lsx_vst(loc1, tmp_odd_buf, 16); + __lsx_vst(loc2, tmp_odd_buf, 32); + __lsx_vst(loc3, tmp_odd_buf, 48); + DUP2_ARG2(__lsx_vsub_h, reg0, reg4, reg1, reg5, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc0, loc1); + + DUP2_ARG2(__lsx_vsub_h, reg2, reg6, reg3, reg7, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 8 * 16); + __lsx_vst(loc1, tmp_odd_buf, 8 * 16 + 16); + __lsx_vst(loc2, tmp_odd_buf, 8 * 16 + 32); + __lsx_vst(loc3, tmp_odd_buf, 8 * 16 + 48); + + /* Load 8 & Store 8 */ + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 4 * 16, tmp_odd_buf, 4 * 16 + 16, + tmp_odd_buf, 4 * 16 + 32, tmp_odd_buf, 4 * 16 + 48, + reg1, reg2, reg0, reg3); + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 12 * 16, tmp_odd_buf, 12 * 16 + 16, + tmp_odd_buf, 12 * 16 + 32, tmp_odd_buf, 12 * 16 + 48, + reg4, reg5, reg6, reg7); + + DUP4_ARG2(__lsx_vadd_h, reg0, reg4, reg1, reg5, reg2, reg6, reg3, reg7, + loc0, loc1, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 4 * 16); + __lsx_vst(loc1, tmp_odd_buf, 4 * 16 + 16); + __lsx_vst(loc2, tmp_odd_buf, 4 * 16 + 32); + __lsx_vst(loc3, tmp_odd_buf, 4 * 16 + 48); + + DUP2_ARG2(__lsx_vsub_h, reg0, reg4, reg3, reg7, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc0, loc1); + + DUP2_ARG2(__lsx_vsub_h, reg1, reg5, reg2, reg6, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 12 * 16); + __lsx_vst(loc1, tmp_odd_buf, 12 * 16 + 16); + __lsx_vst(loc2, tmp_odd_buf, 12 * 16 + 32); + __lsx_vst(loc3, tmp_odd_buf, 12 * 16 + 48); +} + +static void vp9_idct8x32_column_butterfly_addblk(int16_t *tmp_eve_buf, + int16_t *tmp_odd_buf, + uint8_t *dst, + int32_t dst_stride) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i m0, m1, m2, m3, m4, m5, m6, m7, n0, n1, n2, n3, n4, n5, n6, n7; + + /* FINAL BUTTERFLY : Dependency on Even & Odd */ + vec0 = __lsx_vld(tmp_odd_buf, 0); + vec1 = __lsx_vld(tmp_odd_buf, 9 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 14 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 6 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 0); + loc1 = __lsx_vld(tmp_eve_buf, 8 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 4 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 12 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m0, m4, m2, m6); + DUP4_ARG2(__lsx_vsrari_h, m0, 6, m2, 6, m4, 6, m6, 6, m0, m2, m4, m6); + VP9_ADDBLK_ST8x4_UB(dst, (4 * dst_stride), m0, m2, m4, m6); + + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m6, m2, m4, m0); + DUP4_ARG2(__lsx_vsrari_h, m0, 6, m2, 6, m4, 6, m6, 6, m0, m2, m4, m6); + VP9_ADDBLK_ST8x4_UB((dst + 19 * dst_stride), (4 * dst_stride), + m0, m2, m4, m6); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 4 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 13 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 10 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 3 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 2 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 10 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 6 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 14 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m1, m5, m3, m7); + DUP4_ARG2(__lsx_vsrari_h, m1, 6, m3, 6, m5, 6, m7, 6, m1, m3, m5, m7); + VP9_ADDBLK_ST8x4_UB((dst + 2 * dst_stride), (4 * dst_stride), + m1, m3, m5, m7); + + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m7, m3, m5, m1); + DUP4_ARG2(__lsx_vsrari_h, m1, 6, m3, 6, m5, 6, m7, 6, m1, m3, m5, m7); + VP9_ADDBLK_ST8x4_UB((dst + 17 * dst_stride), (4 * dst_stride), + m1, m3, m5, m7); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 2 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 11 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 12 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 7 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 1 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 9 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 5 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 13 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n0, n4, n2, n6); + DUP4_ARG2(__lsx_vsrari_h, n0, 6, n2, 6, n4, 6, n6, 6, n0, n2, n4, n6); + VP9_ADDBLK_ST8x4_UB((dst + 1 * dst_stride), (4 * dst_stride), + n0, n2, n4, n6); + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n6, n2, n4, n0); + DUP4_ARG2(__lsx_vsrari_h, n0, 6, n2, 6, n4, 6, n6, 6, n0, n2, n4, n6); + VP9_ADDBLK_ST8x4_UB((dst + 18 * dst_stride), (4 * dst_stride), + n0, n2, n4, n6); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 5 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 15 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 8 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 1 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 3 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 11 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 7 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 15 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n1, n5, n3, n7); + DUP4_ARG2(__lsx_vsrari_h, n1, 6, n3, 6, n5, 6, n7, 6, n1, n3, n5, n7); + VP9_ADDBLK_ST8x4_UB((dst + 3 * dst_stride), (4 * dst_stride), + n1, n3, n5, n7); + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n7, n3, n5, n1); + DUP4_ARG2(__lsx_vsrari_h, n1, 6, n3, 6, n5, 6, n7, 6, n1, n3, n5, n7); + VP9_ADDBLK_ST8x4_UB((dst + 16 * dst_stride), (4 * dst_stride), + n1, n3, n5, n7); +} + +static void vp9_idct8x32_1d_columns_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int16_t tmp_odd_buf[16 * 8] ALLOC_ALIGNED(16); + int16_t tmp_eve_buf[16 * 8] ALLOC_ALIGNED(16); + + vp9_idct8x32_column_even_process_store(input, &tmp_eve_buf[0]); + vp9_idct8x32_column_odd_process_store(input, &tmp_odd_buf[0]); + vp9_idct8x32_column_butterfly_addblk(&tmp_eve_buf[0], &tmp_odd_buf[0], + dst, dst_stride); +} + +static void vp9_idct8x32_1d_columns_lsx(int16_t *input, int16_t *output, + int16_t *tmp_buf) +{ + int16_t tmp_odd_buf[16 * 8] ALLOC_ALIGNED(16); + int16_t tmp_eve_buf[16 * 8] ALLOC_ALIGNED(16); + + vp9_idct8x32_column_even_process_store(input, &tmp_eve_buf[0]); + vp9_idct8x32_column_odd_process_store(input, &tmp_odd_buf[0]); + vp9_idct_butterfly_transpose_store(tmp_buf, &tmp_eve_buf[0], + &tmp_odd_buf[0], output); +} + +static void vp9_idct32x32_1_add_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out; + uint8_t *dst_tmp = dst + dst_stride; + __m128i zero = __lsx_vldi(0); + __m128i dst0, dst1, dst2, dst3, tmp0, tmp1, tmp2, tmp3; + __m128i res0, res1, res2, res3, res4, res5, res6, res7, vec; + + out = ROUND_POWER_OF_TWO((input[0] * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO((out * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO(out, 6); + input[0] = 0; + + vec = __lsx_vreplgr2vr_h(out); + + for (i = 16; i--;) { + DUP2_ARG2(__lsx_vld, dst, 0, dst, 16, dst0, dst1); + DUP2_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst2, dst3); + + DUP4_ARG2(__lsx_vilvl_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, + res0, res1, res2, res3); + DUP4_ARG2(__lsx_vilvh_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, + res4, res5, res6, res7); + DUP4_ARG2(__lsx_vadd_h, res0, vec, res1, vec, res2, vec, res3, vec, + res0, res1, res2, res3); + DUP4_ARG2(__lsx_vadd_h, res4, vec, res5, vec, res6, vec, res7, vec, + res4, res5, res6, res7); + DUP4_ARG1(__lsx_vclip255_h, res0, res1, res2, res3, res0, res1, res2, res3); + DUP4_ARG1(__lsx_vclip255_h, res4, res5, res6, res7, res4, res5, res6, res7); + DUP4_ARG2(__lsx_vpickev_b, res4, res0, res5, res1, res6, res2, res7, res3, + tmp0, tmp1, tmp2, tmp3); + + __lsx_vst(tmp0, dst, 0); + __lsx_vst(tmp1, dst, 16); + __lsx_vst(tmp2, dst_tmp, 0); + __lsx_vst(tmp3, dst_tmp, 16); + dst = dst_tmp + dst_stride; + dst_tmp = dst + dst_stride; + } +} + +static void vp9_idct32x32_34_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[32 * 32] ALLOC_ALIGNED(16); + int16_t *out_ptr = out_arr; + int16_t tmp_buf[8 * 32] ALLOC_ALIGNED(16); + __m128i zero = __lsx_vldi(0); + + for (i = 16; i--;) { + __lsx_vst(zero, out_ptr, 0); + __lsx_vst(zero, out_ptr, 16); + __lsx_vst(zero, out_ptr, 32); + __lsx_vst(zero, out_ptr, 48); + __lsx_vst(zero, out_ptr, 64); + __lsx_vst(zero, out_ptr, 80); + __lsx_vst(zero, out_ptr, 96); + __lsx_vst(zero, out_ptr, 112); + out_ptr += 64; + } + + out_ptr = out_arr; + + /* process 8*32 block */ + vp9_idct8x32_1d_columns_lsx(input, out_ptr, &tmp_buf[0]); + + /* transform columns */ + for (i = 0; i < 4; i++) { + /* process 8*32 block */ + vp9_idct8x32_1d_columns_addblk_lsx((out_ptr + (i << 3)), + (dst + (i << 3)), dst_stride); + } +} + +static void vp9_idct32x32_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[32 * 32] ALLOC_ALIGNED(16); + int16_t *out_ptr = out_arr; + int16_t tmp_buf[8 * 32] ALLOC_ALIGNED(16); + + /* transform rows */ + for (i = 0; i < 4; i++) { + /* process 8*32 block */ + vp9_idct8x32_1d_columns_lsx((input + (i << 3)), (out_ptr + (i << 8)), + &tmp_buf[0]); + } + + /* transform columns */ + for (i = 0; i < 4; i++) { + /* process 8*32 block */ + vp9_idct8x32_1d_columns_addblk_lsx((out_ptr + (i << 3)), + (dst + (i << 3)), dst_stride); + } +} + +void ff_idct_idct_8x8_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob) +{ + if (eob == 1) { + vp9_idct8x8_1_add_lsx(block, dst, stride); + } + else if (eob <= 12) { + vp9_idct8x8_12_colcol_addblk_lsx(block, dst, stride); + } + else { + vp9_idct8x8_colcol_addblk_lsx(block, dst, stride); + } +} + +void ff_idct_idct_16x16_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob) +{ + if (eob == 1) { + /* DC only DCT coefficient. */ + vp9_idct16x16_1_add_lsx(block, dst, stride); + } + else if (eob <= 10) { + vp9_idct16x16_10_colcol_addblk_lsx(block, dst, stride); + } + else { + vp9_idct16x16_colcol_addblk_lsx(block, dst, stride); + } +} + +void ff_idct_idct_32x32_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob) +{ + if (eob == 1) { + vp9_idct32x32_1_add_lsx(block, dst, stride); + } + else if (eob <= 34) { + vp9_idct32x32_34_colcol_addblk_lsx(block, dst, stride); + } + else { + vp9_idct32x32_colcol_addblk_lsx(block, dst, stride); + } +} diff --git a/libavcodec/loongarch/vp9_lpf_lsx.c b/libavcodec/loongarch/vp9_lpf_lsx.c new file mode 100644 index 0000000000..8e1915b888 --- /dev/null +++ b/libavcodec/loongarch/vp9_lpf_lsx.c @@ -0,0 +1,3141 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Jin Bo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "libavutil/common.h" +#include "vp9dsp_loongarch.h" + +#define LSX_LD_8(_src, _stride, _stride2, _stride3, _stride4, _in0, _in1, _in2, \ + _in3, _in4, _in5, _in6, _in7) \ +{ \ + _in0 = __lsx_vld(_src, 0); \ + _in1 = __lsx_vldx(_src, _stride); \ + _in2 = __lsx_vldx(_src, _stride2); \ + _in3 = __lsx_vldx(_src, _stride3); \ + _src += _stride4; \ + _in4 = __lsx_vld(_src, 0); \ + _in5 = __lsx_vldx(_src, _stride); \ + _in6 = __lsx_vldx(_src, _stride2); \ + _in7 = __lsx_vldx(_src, _stride3); \ +} + +#define LSX_ST_8(_dst0, _dst1, _dst2, _dst3, _dst4, _dst5, _dst6, _dst7, \ + _dst, _stride, _stride2, _stride3, _stride4) \ +{ \ + __lsx_vst(_dst0, _dst, 0); \ + __lsx_vstx(_dst1, _dst, _stride); \ + __lsx_vstx(_dst2, _dst, _stride2); \ + __lsx_vstx(_dst3, _dst, _stride3); \ + _dst += _stride4; \ + __lsx_vst(_dst4, _dst, 0); \ + __lsx_vstx(_dst5, _dst, _stride); \ + __lsx_vstx(_dst6, _dst, _stride2); \ + __lsx_vstx(_dst7, _dst, _stride3); \ +} + +#define VP9_LPF_FILTER4_4W(p1_src, p0_src, q0_src, q1_src, mask_src, hev_src, \ + p1_dst, p0_dst, q0_dst, q1_dst) \ +{ \ + __m128i p1_tmp, p0_tmp, q0_tmp, q1_tmp, q0_sub_p0, filt, filt1, filt2; \ + const __m128i cnst3b = __lsx_vldi(3); \ + const __m128i cnst4b = __lsx_vldi(4); \ + \ + p1_tmp = __lsx_vxori_b(p1_src, 0x80); \ + p0_tmp = __lsx_vxori_b(p0_src, 0x80); \ + q0_tmp = __lsx_vxori_b(q0_src, 0x80); \ + q1_tmp = __lsx_vxori_b(q1_src, 0x80); \ + \ + filt = __lsx_vssub_b(p1_tmp, q1_tmp); \ + \ + filt = filt & hev_src; \ + \ + q0_sub_p0 = __lsx_vssub_b(q0_tmp, p0_tmp); \ + filt = __lsx_vsadd_b(filt, q0_sub_p0); \ + filt = __lsx_vsadd_b(filt, q0_sub_p0); \ + filt = __lsx_vsadd_b(filt, q0_sub_p0); \ + filt = filt & mask_src; \ + \ + filt1 = __lsx_vsadd_b(filt, cnst4b); \ + filt1 = __lsx_vsrai_b(filt1, 3); \ + \ + filt2 = __lsx_vsadd_b(filt, cnst3b); \ + filt2 = __lsx_vsrai_b(filt2, 3); \ + \ + q0_tmp = __lsx_vssub_b(q0_tmp, filt1); \ + q0_dst = __lsx_vxori_b(q0_tmp, 0x80); \ + p0_tmp = __lsx_vsadd_b(p0_tmp, filt2); \ + p0_dst = __lsx_vxori_b(p0_tmp, 0x80); \ + \ + filt = __lsx_vsrari_b(filt1, 1); \ + hev_src = __lsx_vxori_b(hev_src, 0xff); \ + filt = filt & hev_src; \ + \ + q1_tmp = __lsx_vssub_b(q1_tmp, filt); \ + q1_dst = __lsx_vxori_b(q1_tmp, 0x80); \ + p1_tmp = __lsx_vsadd_b(p1_tmp, filt); \ + p1_dst = __lsx_vxori_b(p1_tmp, 0x80); \ +} + +#define VP9_FLAT4(p3_src, p2_src, p0_src, q0_src, q2_src, q3_src, flat_dst) \ +{ \ + __m128i f_tmp = __lsx_vldi(1); \ + __m128i p2_a_sub_p0, q2_a_sub_q0, p3_a_sub_p0, q3_a_sub_q0; \ + \ + p2_a_sub_p0 = __lsx_vabsd_bu(p2_src, p0_src); \ + q2_a_sub_q0 = __lsx_vabsd_bu(q2_src, q0_src); \ + p3_a_sub_p0 = __lsx_vabsd_bu(p3_src, p0_src); \ + q3_a_sub_q0 = __lsx_vabsd_bu(q3_src, q0_src); \ + \ + p2_a_sub_p0 = __lsx_vmax_bu(p2_a_sub_p0, q2_a_sub_q0); \ + flat_dst = __lsx_vmax_bu(p2_a_sub_p0, flat_dst); \ + p3_a_sub_p0 = __lsx_vmax_bu(p3_a_sub_p0, q3_a_sub_q0); \ + flat_dst = __lsx_vmax_bu(p3_a_sub_p0, flat_dst); \ + \ + flat_dst = __lsx_vslt_bu(f_tmp, flat_dst); \ + flat_dst = __lsx_vxori_b(flat_dst, 0xff); \ + flat_dst = flat_dst & mask; \ +} + +#define VP9_FLAT5(p7_src, p6_src, p5_src, p4_src, p0_src, q0_src, q4_src, \ + q5_src, q6_src, q7_src, flat_src, flat2_dst) \ +{ \ + __m128i f_tmp = __lsx_vldi(1); \ + __m128i p4_a_sub_p0, q4_a_sub_q0, p5_a_sub_p0, q5_a_sub_q0; \ + __m128i p6_a_sub_p0, q6_a_sub_q0, p7_a_sub_p0, q7_a_sub_q0; \ + \ + p4_a_sub_p0 = __lsx_vabsd_bu(p4_src, p0_src); \ + q4_a_sub_q0 = __lsx_vabsd_bu(q4_src, q0_src); \ + p5_a_sub_p0 = __lsx_vabsd_bu(p5_src, p0_src); \ + q5_a_sub_q0 = __lsx_vabsd_bu(q5_src, q0_src); \ + p6_a_sub_p0 = __lsx_vabsd_bu(p6_src, p0_src); \ + q6_a_sub_q0 = __lsx_vabsd_bu(q6_src, q0_src); \ + p7_a_sub_p0 = __lsx_vabsd_bu(p7_src, p0_src); \ + q7_a_sub_q0 = __lsx_vabsd_bu(q7_src, q0_src); \ + \ + p4_a_sub_p0 = __lsx_vmax_bu(p4_a_sub_p0, q4_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p5_a_sub_p0, q5_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p4_a_sub_p0, flat2_dst); \ + p6_a_sub_p0 = __lsx_vmax_bu(p6_a_sub_p0, q6_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p6_a_sub_p0, flat2_dst); \ + p7_a_sub_p0 = __lsx_vmax_bu(p7_a_sub_p0, q7_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p7_a_sub_p0, flat2_dst); \ + \ + flat2_dst = __lsx_vslt_bu(f_tmp, flat2_dst); \ + flat2_dst = __lsx_vxori_b(flat2_dst, 0xff); \ + flat2_dst = flat2_dst & flat_src; \ +} + +#define VP9_FILTER8(p3_src, p2_src, p1_src, p0_src, \ + q0_src, q1_src, q2_src, q3_src, \ + p2_filt8_dst, p1_filt8_dst, p0_filt8_dst, \ + q0_filt8_dst, q1_filt8_dst, q2_filt8_dst) \ +{ \ + __m128i tmp0, tmp1, tmp2; \ + \ + tmp2 = __lsx_vadd_h(p2_src, p1_src); \ + tmp2 = __lsx_vadd_h(tmp2, p0_src); \ + tmp0 = __lsx_vslli_h(p3_src, 1); \ + \ + tmp0 = __lsx_vadd_h(tmp0, tmp2); \ + tmp0 = __lsx_vadd_h(tmp0, q0_src); \ + tmp1 = __lsx_vadd_h(tmp0, p3_src); \ + tmp1 = __lsx_vadd_h(tmp1, p2_src); \ + p2_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp1 = __lsx_vadd_h(tmp0, p1_src); \ + tmp1 = __lsx_vadd_h(tmp1, q1_src); \ + p1_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp1 = __lsx_vadd_h(q2_src, q1_src); \ + tmp1 = __lsx_vadd_h(tmp1, q0_src); \ + tmp2 = __lsx_vadd_h(tmp2, tmp1); \ + tmp0 = __lsx_vadd_h(tmp2, p0_src); \ + tmp0 = __lsx_vadd_h(tmp0, p3_src); \ + p0_filt8_dst = __lsx_vsrari_h(tmp0, 3); \ + \ + tmp0 = __lsx_vadd_h(q2_src, q3_src); \ + tmp0 = __lsx_vadd_h(tmp0, p0_src); \ + tmp0 = __lsx_vadd_h(tmp0, tmp1); \ + tmp1 = __lsx_vadd_h(q3_src, q3_src); \ + tmp1 = __lsx_vadd_h(tmp1, tmp0); \ + q2_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp0 = __lsx_vadd_h(tmp2, q3_src); \ + tmp1 = __lsx_vadd_h(tmp0, q0_src); \ + q0_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp1 = __lsx_vsub_h(tmp0, p2_src); \ + tmp0 = __lsx_vadd_h(q1_src, q3_src); \ + tmp1 = __lsx_vadd_h(tmp0, tmp1); \ + q1_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ +} + +#define LPF_MASK_HEV(p3_src, p2_src, p1_src, p0_src, q0_src, q1_src, \ + q2_src, q3_src, limit_src, b_limit_src, thresh_src, \ + hev_dst, mask_dst, flat_dst) \ +{ \ + __m128i p3_asub_p2_tmp, p2_asub_p1_tmp, p1_asub_p0_tmp, q1_asub_q0_tmp; \ + __m128i p1_asub_q1_tmp, p0_asub_q0_tmp, q3_asub_q2_tmp, q2_asub_q1_tmp; \ + \ + /* absolute subtraction of pixel values */ \ + p3_asub_p2_tmp = __lsx_vabsd_bu(p3_src, p2_src); \ + p2_asub_p1_tmp = __lsx_vabsd_bu(p2_src, p1_src); \ + p1_asub_p0_tmp = __lsx_vabsd_bu(p1_src, p0_src); \ + q1_asub_q0_tmp = __lsx_vabsd_bu(q1_src, q0_src); \ + q2_asub_q1_tmp = __lsx_vabsd_bu(q2_src, q1_src); \ + q3_asub_q2_tmp = __lsx_vabsd_bu(q3_src, q2_src); \ + p0_asub_q0_tmp = __lsx_vabsd_bu(p0_src, q0_src); \ + p1_asub_q1_tmp = __lsx_vabsd_bu(p1_src, q1_src); \ + \ + /* calculation of hev */ \ + flat_dst = __lsx_vmax_bu(p1_asub_p0_tmp, q1_asub_q0_tmp); \ + hev_dst = __lsx_vslt_bu(thresh_src, flat_dst); \ + \ + /* calculation of mask */ \ + p0_asub_q0_tmp = __lsx_vsadd_bu(p0_asub_q0_tmp, p0_asub_q0_tmp); \ + p1_asub_q1_tmp = __lsx_vsrli_b(p1_asub_q1_tmp, 1); \ + p0_asub_q0_tmp = __lsx_vsadd_bu(p0_asub_q0_tmp, p1_asub_q1_tmp); \ + \ + mask_dst = __lsx_vslt_bu(b_limit_src, p0_asub_q0_tmp); \ + mask_dst = __lsx_vmax_bu(flat_dst, mask_dst); \ + p3_asub_p2_tmp = __lsx_vmax_bu(p3_asub_p2_tmp, p2_asub_p1_tmp); \ + mask_dst = __lsx_vmax_bu(p3_asub_p2_tmp, mask_dst); \ + q2_asub_q1_tmp = __lsx_vmax_bu(q2_asub_q1_tmp, q3_asub_q2_tmp); \ + mask_dst = __lsx_vmax_bu(q2_asub_q1_tmp, mask_dst); \ + \ + mask_dst = __lsx_vslt_bu(limit_src, mask_dst); \ + mask_dst = __lsx_vxori_b(mask_dst, 0xff); \ +} + +void ff_loop_filter_v_4_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i mask, hev, flat, thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0, p1_out, p0_out, q0_out, q1_out; + + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst , 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); +} + +void ff_loop_filter_v_44_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i mask, hev, flat, thresh0, b_limit0; + __m128i limit0, thresh1, b_limit1, limit1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh0 = __lsx_vreplgr2vr_b(thresh_ptr); + thresh1 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh0 = __lsx_vilvl_d(thresh1, thresh0); + + b_limit0 = __lsx_vreplgr2vr_b(b_limit_ptr); + b_limit1 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit0 = __lsx_vilvl_d(b_limit1, b_limit0); + + limit0 = __lsx_vreplgr2vr_b(limit_ptr); + limit1 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit0 = __lsx_vilvl_d(limit1, limit0); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1, p0, q0, q1); + + __lsx_vst(p1, dst - stride2, 0); + __lsx_vst(p0, dst - stride, 0); + __lsx_vst(q0, dst , 0); + __lsx_vst(q1, dst + stride, 0); +} + +void ff_loop_filter_v_8_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i mask, hev, flat, thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i p2_filter8, p1_filter8, p0_filter8; + __m128i q0_filter8, q1_filter8, q2_filter8; + __m128i p3_l, p2_l, p1_l, p0_l, q3_l, q2_l, q1_l, q0_l; + __m128i zero = __lsx_vldi(0); + + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst , 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filter8, + p1_filter8, p0_filter8, q0_filter8, q1_filter8, q2_filter8); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, zero, p2_filter8, zero, p1_filter8, + zero, p0_filter8, zero, q0_filter8, p2_filter8, + p1_filter8, p0_filter8, q0_filter8); + DUP2_ARG2(__lsx_vpickev_b, zero, q1_filter8, zero, q2_filter8, + q1_filter8, q2_filter8); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filter8, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filter8, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filter8, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filter8, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filter8, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filter8, flat); + + __lsx_vstelm_d(p2_out, dst - stride3, 0, 0); + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst, 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); + __lsx_vstelm_d(q2_out, dst + stride2, 0, 0); + } +} + +void ff_loop_filter_v_88_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, tmp, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + tmp = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(tmp, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + tmp = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(tmp, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + tmp = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(tmp, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vst(p1_out, dst - stride2, 0); + __lsx_vst(p0_out, dst - stride, 0); + __lsx_vst(q0_out, dst, 0); + __lsx_vst(q1_out, dst + stride, 0); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + + __lsx_vstx(p2_out, dst, -stride3); + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + __lsx_vstx(q2_out, dst, stride2); + } +} + +void ff_loop_filter_v_84_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, tmp, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + tmp = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(tmp, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + tmp = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(tmp, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + tmp = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(tmp, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_l, p2_filt8_l, p1_filt8_l, + p1_filt8_l, p0_filt8_l, p0_filt8_l, q0_filt8_l, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_l, q1_filt8_l, q2_filt8_l, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + __lsx_vstx(p2_out, dst, -stride3); + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + __lsx_vstx(q2_out, dst, stride2); + } +} + +void ff_loop_filter_v_48_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, tmp, thresh, b_limit, limit; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i zero = { 0 }; + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + tmp = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(tmp, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + tmp = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(tmp, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + tmp = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(tmp, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvh_d(flat, zero); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + } else { + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_h, p1_filt8_h, + p1_filt8_h, p0_filt8_h, p0_filt8_h, q0_filt8_h, q0_filt8_h, + p2_filt8_h, p1_filt8_h, p0_filt8_h, q0_filt8_h); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_h, q2_filt8_h, + q2_filt8_h, q1_filt8_h, q2_filt8_h); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_h, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_h, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_h, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_h, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_h, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_h, flat); + + __lsx_vstx(p2_out, dst, -stride3); + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + __lsx_vstx(q2_out, dst, stride2); + } +} + +static int32_t vp9_hz_lpf_t4_and_t8_16w(uint8_t *dst, ptrdiff_t stride, + uint8_t *filter48, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + return 1; + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + __lsx_vst(p2_out, filter48, 0); + __lsx_vst(p1_out, filter48, 16); + __lsx_vst(p0_out, filter48, 32); + __lsx_vst(q0_out, filter48, 48); + __lsx_vst(q1_out, filter48, 64); + __lsx_vst(q2_out, filter48, 80); + __lsx_vst(flat, filter48, 96); + + return 0; + } +} + +static void vp9_hz_lpf_t16_16w(uint8_t *dst, ptrdiff_t stride, + uint8_t *filter48) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - stride4; + uint8_t *dst_tmp1 = dst + stride4; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + __m128i flat, flat2, filter8; + __m128i zero = __lsx_vldi(0); + __m128i out_h, out_l; + v8u16 p7_l_in, p6_l_in, p5_l_in, p4_l_in; + v8u16 p3_l_in, p2_l_in, p1_l_in, p0_l_in; + v8u16 q7_l_in, q6_l_in, q5_l_in, q4_l_in; + v8u16 q3_l_in, q2_l_in, q1_l_in, q0_l_in; + v8u16 p7_h_in, p6_h_in, p5_h_in, p4_h_in; + v8u16 p3_h_in, p2_h_in, p1_h_in, p0_h_in; + v8u16 q7_h_in, q6_h_in, q5_h_in, q4_h_in; + v8u16 q3_h_in, q2_h_in, q1_h_in, q0_h_in; + v8u16 tmp0_l, tmp1_l, tmp0_h, tmp1_h; + + flat = __lsx_vld(filter48, 96); + + DUP4_ARG2(__lsx_vldx, dst_tmp, -stride4, dst_tmp, -stride3, dst_tmp, + -stride2, dst_tmp, -stride, p7, p6, p5, p4); + p3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p2, p1); + p0 = __lsx_vldx(dst_tmp, stride3); + + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + q4 = __lsx_vld(dst_tmp1, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp1, stride, dst_tmp1, stride2, q5, q6); + q7 = __lsx_vldx(dst_tmp1, stride3); + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + DUP4_ARG2(__lsx_vld, filter48, 0, filter48, 16, filter48, 32, filter48, + 48, p2, p1, p0, q0); + DUP2_ARG2(__lsx_vld, filter48, 64, filter48, 80, q1, q2); + + __lsx_vstx(p2, dst, -stride3); + __lsx_vstx(p1, dst, -stride2); + __lsx_vstx(p0, dst, -stride); + __lsx_vst(q0, dst, 0); + __lsx_vstx(q1, dst, stride); + __lsx_vstx(q2, dst, stride2); + } else { + dst = dst_tmp - stride3; + + p7_l_in = (v8u16)__lsx_vilvl_b(zero, p7); + p6_l_in = (v8u16)__lsx_vilvl_b(zero, p6); + p5_l_in = (v8u16)__lsx_vilvl_b(zero, p5); + p4_l_in = (v8u16)__lsx_vilvl_b(zero, p4); + p3_l_in = (v8u16)__lsx_vilvl_b(zero, p3); + p2_l_in = (v8u16)__lsx_vilvl_b(zero, p2); + p1_l_in = (v8u16)__lsx_vilvl_b(zero, p1); + p0_l_in = (v8u16)__lsx_vilvl_b(zero, p0); + + q0_l_in = (v8u16)__lsx_vilvl_b(zero, q0); + + tmp0_l = p7_l_in << 3; + tmp0_l -= p7_l_in; + tmp0_l += p6_l_in; + tmp0_l += q0_l_in; + tmp1_l = p6_l_in + p5_l_in; + tmp1_l += p4_l_in; + tmp1_l += p3_l_in; + tmp1_l += p2_l_in; + tmp1_l += p1_l_in; + tmp1_l += p0_l_in; + tmp1_l += tmp0_l; + + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + p7_h_in = (v8u16)__lsx_vilvh_b(zero, p7); + p6_h_in = (v8u16)__lsx_vilvh_b(zero, p6); + p5_h_in = (v8u16)__lsx_vilvh_b(zero, p5); + p4_h_in = (v8u16)__lsx_vilvh_b(zero, p4); + + p3_h_in = (v8u16)__lsx_vilvh_b(zero, p3); + p2_h_in = (v8u16)__lsx_vilvh_b(zero, p2); + p1_h_in = (v8u16)__lsx_vilvh_b(zero, p1); + p0_h_in = (v8u16)__lsx_vilvh_b(zero, p0); + q0_h_in = (v8u16)__lsx_vilvh_b(zero, q0); + + tmp0_h = p7_h_in << 3; + tmp0_h -= p7_h_in; + tmp0_h += p6_h_in; + tmp0_h += q0_h_in; + tmp1_h = p6_h_in + p5_h_in; + tmp1_h += p4_h_in; + tmp1_h += p3_h_in; + tmp1_h += p2_h_in; + tmp1_h += p1_h_in; + tmp1_h += p0_h_in; + tmp1_h += tmp0_h; + + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p6 = __lsx_vbitsel_v(p6, out_l, flat2); + __lsx_vst(p6, dst, 0); + dst += stride; + + /* p5 */ + q1_l_in = (v8u16)__lsx_vilvl_b(zero, q1); + tmp0_l = p5_l_in - p6_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q1_h_in = (v8u16)__lsx_vilvh_b(zero, q1); + tmp0_h = p5_h_in - p6_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p5 = __lsx_vbitsel_v(p5, out_l, flat2); + __lsx_vst(p5, dst, 0); + dst += stride; + + /* p4 */ + q2_l_in = (v8u16)__lsx_vilvl_b(zero, q2); + tmp0_l = p4_l_in - p5_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q2_h_in = (v8u16)__lsx_vilvh_b(zero, q2); + tmp0_h = p4_h_in - p5_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p4 = __lsx_vbitsel_v(p4, out_l, flat2); + __lsx_vst(p4, dst, 0); + dst += stride; + + /* p3 */ + q3_l_in = (v8u16)__lsx_vilvl_b(zero, q3); + tmp0_l = p3_l_in - p4_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q3_h_in = (v8u16)__lsx_vilvh_b(zero, q3); + tmp0_h = p3_h_in - p4_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p3 = __lsx_vbitsel_v(p3, out_l, flat2); + __lsx_vst(p3, dst, 0); + dst += stride; + + /* p2 */ + q4_l_in = (v8u16)__lsx_vilvl_b(zero, q4); + filter8 = __lsx_vld(filter48, 0); + tmp0_l = p2_l_in - p3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q4_h_in = (v8u16)__lsx_vilvh_b(zero, q4); + tmp0_h = p2_h_in - p3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* p1 */ + q5_l_in = (v8u16)__lsx_vilvl_b(zero, q5); + filter8 = __lsx_vld(filter48, 16); + tmp0_l = p1_l_in - p2_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q5_h_in = (v8u16)__lsx_vilvh_b(zero, q5); + tmp0_h = p1_h_in - p2_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* p0 */ + q6_l_in = (v8u16)__lsx_vilvl_b(zero, q6); + filter8 = __lsx_vld(filter48, 32); + tmp0_l = p0_l_in - p1_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q6_h_in = (v8u16)__lsx_vilvh_b(zero, q6); + tmp0_h = p0_h_in - p1_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q0 */ + q7_l_in = (v8u16)__lsx_vilvl_b(zero, q7); + filter8 = __lsx_vld(filter48, 48); + tmp0_l = q7_l_in - p0_l_in; + tmp0_l += q0_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q7_h_in = (v8u16)__lsx_vilvh_b(zero, q7); + tmp0_h = q7_h_in - p0_h_in; + tmp0_h += q0_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q1 */ + filter8 = __lsx_vld(filter48, 64); + tmp0_l = q7_l_in - q0_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p6_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q0_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p6_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q2 */ + filter8 = __lsx_vld(filter48, 80); + tmp0_l = q7_l_in - q1_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p5_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q1_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p5_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q3 */ + tmp0_l = q7_l_in - q2_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p4_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q2_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p4_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q3 = __lsx_vbitsel_v(q3, out_l, flat2); + __lsx_vst(q3, dst, 0); + dst += stride; + + /* q4 */ + tmp0_l = q7_l_in - q3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p3_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p3_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q4 = __lsx_vbitsel_v(q4, out_l, flat2); + __lsx_vst(q4, dst, 0); + dst += stride; + + /* q5 */ + tmp0_l = q7_l_in - q4_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p2_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q4_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p2_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q5 = __lsx_vbitsel_v(q5, out_l, flat2); + __lsx_vst(q5, dst, 0); + dst += stride; + + /* q6 */ + tmp0_l = q7_l_in - q5_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p1_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q5_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p1_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q6 = __lsx_vbitsel_v(q6, out_l, flat2); + __lsx_vst(q6, dst, 0); + } +} + +void ff_loop_filter_v_16_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + uint8_t filter48[16 * 8] __attribute__ ((aligned(16))); + uint8_t early_exit = 0; + + early_exit = vp9_hz_lpf_t4_and_t8_16w(dst, stride, &filter48[0], + b_limit_ptr, limit_ptr, thresh_ptr); + + if (0 == early_exit) { + vp9_hz_lpf_t16_16w(dst, stride, filter48); + } +} + +void ff_loop_filter_v_16_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - stride4; + uint8_t *dst_tmp1 = dst + stride4; + __m128i zero = __lsx_vldi(0); + __m128i flat2, mask, hev, flat, thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0, p7, p6, p5, p4, q4, q5, q6, q7; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i p0_filter16, p1_filter16; + __m128i p2_filter8, p1_filter8, p0_filter8; + __m128i q0_filter8, q1_filter8, q2_filter8; + __m128i p7_l, p6_l, p5_l, p4_l, q7_l, q6_l, q5_l, q4_l; + __m128i p3_l, p2_l, p1_l, p0_l, q3_l, q2_l, q1_l, q0_l; + __m128i tmp0, tmp1, tmp2; + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst , 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); + } else { + /* convert 8 bit input data into 16 bit */ + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, + p2_filter8, p1_filter8, p0_filter8, q0_filter8, + q1_filter8, q2_filter8); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, zero, p2_filter8, zero, p1_filter8, + zero, p0_filter8, zero, q0_filter8, p2_filter8, + p1_filter8, p0_filter8, q0_filter8); + DUP2_ARG2(__lsx_vpickev_b, zero, q1_filter8, zero, q2_filter8, + q1_filter8, q2_filter8); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filter8, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filter8, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filter8, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filter8, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filter8, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filter8, flat); + + /* load 16 vector elements */ + DUP4_ARG2(__lsx_vld, dst_tmp - stride4, 0, dst_tmp - stride3, 0, + dst_tmp - stride2, 0, dst_tmp - stride, 0, p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, dst_tmp1, 0, dst_tmp1 + stride, 0, + dst_tmp1 + stride2, 0, dst_tmp1 + stride3, 0, q4, q5, q6, q7); + + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + dst -= stride3; + __lsx_vstelm_d(p2_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p0_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(q0_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(q1_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(q2_out, dst, 0, 0); + } else { + /* LSB(right) 8 pixel operation */ + DUP4_ARG2(__lsx_vilvl_b, zero, p7, zero, p6, zero, p5, zero, p4, + p7_l, p6_l, p5_l, p4_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q4, zero, q5, zero, q6, zero, q7, + q4_l, q5_l, q6_l, q7_l); + + tmp0 = __lsx_vslli_h(p7_l, 3); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp0 = __lsx_vadd_h(tmp0, p6_l); + tmp0 = __lsx_vadd_h(tmp0, q0_l); + + dst = dst_tmp - stride3; + + /* calculation of p6 and p5 */ + tmp1 = __lsx_vadd_h(p6_l, p5_l); + tmp1 = __lsx_vadd_h(tmp1, p4_l); + tmp1 = __lsx_vadd_h(tmp1, p3_l); + tmp1 = __lsx_vadd_h(tmp1, p2_l); + tmp1 = __lsx_vadd_h(tmp1, p1_l); + tmp1 = __lsx_vadd_h(tmp1, p0_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp0 = __lsx_vsub_h(p5_l, p6_l); + tmp0 = __lsx_vadd_h(tmp0, q1_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p6, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(p5, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of p4 and p3 */ + tmp0 = __lsx_vsub_h(p4_l, p5_l); + tmp0 = __lsx_vadd_h(tmp0, q2_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp2 = __lsx_vsub_h(p3_l, p4_l); + tmp2 = __lsx_vadd_h(tmp2, q3_l); + tmp2 = __lsx_vsub_h(tmp2, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p4, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(p3, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of p2 and p1 */ + tmp0 = __lsx_vsub_h(p2_l, p3_l); + tmp0 = __lsx_vadd_h(tmp0, q4_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp2 = __lsx_vsub_h(p1_l, p2_l); + tmp2 = __lsx_vadd_h(tmp2, q5_l); + tmp2 = __lsx_vsub_h(tmp2, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p2_out, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(p1_out, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of p0 and q0 */ + tmp0 = __lsx_vsub_h(p0_l, p1_l); + tmp0 = __lsx_vadd_h(tmp0, q6_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp2 = __lsx_vsub_h(q7_l, p0_l); + tmp2 = __lsx_vadd_h(tmp2, q0_l); + tmp2 = __lsx_vsub_h(tmp2, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h((__m128i)tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h((__m128i)tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p0_out, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q0_out, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of q1 and q2 */ + tmp0 = __lsx_vsub_h(q7_l, q0_l); + tmp0 = __lsx_vadd_h(tmp0, q1_l); + tmp0 = __lsx_vsub_h(tmp0, p6_l); + tmp2 = __lsx_vsub_h(q7_l, q1_l); + tmp2 = __lsx_vadd_h(tmp2, q2_l); + tmp2 = __lsx_vsub_h(tmp2, p5_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(q1_out, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q2_out, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of q3 and q4 */ + tmp0 = __lsx_vsub_h(q7_l, q2_l); + tmp0 = __lsx_vadd_h(tmp0, q3_l); + tmp0 = __lsx_vsub_h(tmp0, p4_l); + tmp2 = __lsx_vsub_h(q7_l, q3_l); + tmp2 = __lsx_vadd_h(tmp2, q4_l); + tmp2 = __lsx_vsub_h(tmp2, p3_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(q3, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q4, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of q5 and q6 */ + tmp0 = __lsx_vsub_h(q7_l, q4_l); + tmp0 = __lsx_vadd_h(tmp0, q5_l); + tmp0 = __lsx_vsub_h(tmp0, p2_l); + tmp2 = __lsx_vsub_h(q7_l, q5_l); + tmp2 = __lsx_vadd_h(tmp2, q6_l); + tmp2 = __lsx_vsub_h(tmp2, p1_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(q5, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q6, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + } + } +} + +void ff_loop_filter_h_4_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp1 = dst - 4; + uint8_t *dst_tmp2 = dst_tmp1 + stride4; + __m128i mask, hev, flat, limit, thresh, b_limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i vec0, vec1, vec2, vec3; + + p3 = __lsx_vld(dst_tmp1, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp1, stride, dst_tmp1, stride2, p2, p1); + p0 = __lsx_vldx(dst_tmp1, stride3); + q0 = __lsx_vld(dst_tmp2, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp2, stride, dst_tmp2, stride2, q1, q2); + q3 = __lsx_vldx(dst_tmp2, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LSX_TRANSPOSE8x8_B(p3, p2, p1, p0, q0, q1, q2, q3, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1, p0, q0, q1); + DUP2_ARG2(__lsx_vilvl_b, p0, p1, q1, q0, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); +} + +void ff_loop_filter_h_44_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i mask, hev, flat; + __m128i thresh0, b_limit0, limit0, thresh1, b_limit1, limit1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i row8, row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + + row0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row1, row2); + row3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row8 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row9, row10); + row11 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh0 = __lsx_vreplgr2vr_b(thresh_ptr); + thresh1 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh0 = __lsx_vilvl_d(thresh1, thresh0); + + b_limit0 = __lsx_vreplgr2vr_b(b_limit_ptr); + b_limit1 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit0 = __lsx_vilvl_d(b_limit1, b_limit0); + + limit0 = __lsx_vreplgr2vr_b(limit_ptr); + limit1 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit0 = __lsx_vilvl_d(limit1, limit0); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1, p0, q0, q1); + DUP2_ARG2(__lsx_vilvl_b, p0, p1, q1, q0, tmp0, tmp1); + tmp2 = __lsx_vilvl_h(tmp1, tmp0); + tmp3 = __lsx_vilvh_h(tmp1, tmp0); + DUP2_ARG2(__lsx_vilvh_b, p0, p1, q1, q0, tmp0, tmp1); + tmp4 = __lsx_vilvl_h(tmp1, tmp0); + tmp5 = __lsx_vilvh_h(tmp1, tmp0); + + dst -= 2; + __lsx_vstelm_w(tmp2, dst, 0, 0); + __lsx_vstelm_w(tmp2, dst + stride, 0, 1); + __lsx_vstelm_w(tmp2, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(tmp3, dst, 0, 0); + __lsx_vstelm_w(tmp3, dst + stride, 0, 1); + __lsx_vstelm_w(tmp3, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(tmp4, dst, 0, 0); + __lsx_vstelm_w(tmp4, dst + stride, 0, 1); + __lsx_vstelm_w(tmp4, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(tmp5, dst, 0, 0); + __lsx_vstelm_w(tmp5, dst + stride, 0, 1); + __lsx_vstelm_w(tmp5, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp5, dst + stride3, 0, 3); +} + +void ff_loop_filter_h_8_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i vec0, vec1, vec2, vec3, vec4; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + p3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p2, p1); + p0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q1, q2); + q3 = __lsx_vldx(dst_tmp, stride3); + + LSX_TRANSPOSE8x8_B(p3, p2, p1, p0, q0, q1, q2, q3, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + /* Store 4 pixels p1-_q1 */ + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_l, p2_filt8_l, p1_filt8_l, + p1_filt8_l, p0_filt8_l, p0_filt8_l, q0_filt8_l, + q0_filt8_l, p2_filt8_l, p1_filt8_l, p0_filt8_l, + q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_l, q1_filt8_l, q2_filt8_l, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + /* Store 6 pixels p2-_q2 */ + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + vec4 = __lsx_vilvl_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_h(vec4, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec2, dst, 0, 1); + __lsx_vstelm_h(vec4, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec2, dst, 0, 2); + __lsx_vstelm_h(vec4, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec2, dst, 0, 3); + __lsx_vstelm_h(vec4, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec4, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec4, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec4, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec4, dst, 4, 7); + } +} + +void ff_loop_filter_h_88_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i row4, row5, row6, row7, row12, row13, row14, row15; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i zero = __lsx_vldi(0); + + p0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p1, p2); + p3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q2, q1); + q0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + /* transpose 16x8 matrix into 8x16 */ + LSX_TRANSPOSE16x8_B(p0, p1, p2, p3, row4, row5, row6, row7, + q3, q2, q1, q0, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + vec0 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(vec0, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + vec0 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(vec0, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + vec0 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(vec0, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_w(vec4, dst + stride, 0, 1); + __lsx_vstelm_w(vec4, dst + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec5, dst, 0, 0); + __lsx_vstelm_w(vec5, dst + stride, 0, 1); + __lsx_vstelm_w(vec5, dst + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + + /* filter8 */ + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 7); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 7); + } +} + +void ff_loop_filter_h_84_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i row4, row5, row6, row7, row12, row13, row14, row15; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i zero = __lsx_vldi(0); + + p0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p1, p2); + p3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q2, q1); + q0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + /* transpose 16x8 matrix into 8x16 */ + LSX_TRANSPOSE16x8_B(p0, p1, p2, p3, row4, row5, row6, row7, + q3, q2, q1, q0, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + vec0 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(vec0, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + vec0 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(vec0, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + vec0 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(vec0, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_w(vec4, dst + stride, 0, 1); + __lsx_vstelm_w(vec4, dst + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec5, dst, 0, 0); + __lsx_vstelm_w(vec5, dst + stride, 0, 1); + __lsx_vstelm_w(vec5, dst + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_l, p2_filt8_l, p1_filt8_l, p1_filt8_l, + p0_filt8_l, p0_filt8_l, q0_filt8_l, q0_filt8_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_l, q1_filt8_l, q2_filt8_l, q2_filt8_l, + q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 7); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 7); + } +} + +void ff_loop_filter_h_48_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i row4, row5, row6, row7, row12, row13, row14, row15; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i zero = __lsx_vldi(0); + + p0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p1, p2); + p3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q2, q1); + q0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + /* transpose 16x8 matrix into 8x16 */ + LSX_TRANSPOSE16x8_B(p0, p1, p2, p3, row4, row5, row6, row7, + q3, q2, q1, q0, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + vec0 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(vec0, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + vec0 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(vec0, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + vec0 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(vec0, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvh_d(flat, zero); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_w(vec4, dst + stride, 0, 1); + __lsx_vstelm_w(vec4, dst + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec5, dst, 0, 0); + __lsx_vstelm_w(vec5, dst + stride, 0, 1); + __lsx_vstelm_w(vec5, dst + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_h, p1_filt8_h, + p1_filt8_h, p0_filt8_h, p0_filt8_h, q0_filt8_h, q0_filt8_h, + p2_filt8_h, p1_filt8_h, p0_filt8_h, q0_filt8_h); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_h, q2_filt8_h, + q2_filt8_h, q1_filt8_h, q2_filt8_h); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_h, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_h, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_h, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_h, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_h, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_h, flat); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 7); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 7); + } +} + +static void vp9_transpose_16x8_to_8x16(uint8_t *input, ptrdiff_t in_pitch, + uint8_t *output) +{ + __m128i p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, p0_org; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + ptrdiff_t in_pitch2 = in_pitch << 1; + ptrdiff_t in_pitch3 = in_pitch2 + in_pitch; + ptrdiff_t in_pitch4 = in_pitch2 << 1; + + LSX_LD_8(input, in_pitch, in_pitch2, in_pitch3, in_pitch4, + p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, p0_org); + /* 8x8 transpose */ + LSX_TRANSPOSE8x8_B(p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, + p0_org, p7, p6, p5, p4, p3, p2, p1, p0); + /* 8x8 transpose */ + DUP4_ARG2(__lsx_vilvh_b, p5_org, p7_org, p4_org, p6_org, p1_org, + p3_org, p0_org, p2_org, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_b, tmp1, tmp0, tmp3, tmp2, tmp4, tmp6); + DUP2_ARG2(__lsx_vilvh_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp7); + DUP2_ARG2(__lsx_vilvl_w, tmp6, tmp4, tmp7, tmp5, q0, q4); + DUP2_ARG2(__lsx_vilvh_w, tmp6, tmp4, tmp7, tmp5, q2, q6); + DUP4_ARG2(__lsx_vbsrl_v, q0, 8, q2, 8, q4, 8, q6, 8, q1, q3, q5, q7); + + __lsx_vst(p7, output, 0); + __lsx_vst(p6, output, 16); + __lsx_vst(p5, output, 32); + __lsx_vst(p4, output, 48); + __lsx_vst(p3, output, 64); + __lsx_vst(p2, output, 80); + __lsx_vst(p1, output, 96); + __lsx_vst(p0, output, 112); + __lsx_vst(q0, output, 128); + __lsx_vst(q1, output, 144); + __lsx_vst(q2, output, 160); + __lsx_vst(q3, output, 176); + __lsx_vst(q4, output, 192); + __lsx_vst(q5, output, 208); + __lsx_vst(q6, output, 224); + __lsx_vst(q7, output, 240); +} + +static void vp9_transpose_8x16_to_16x8(uint8_t *input, uint8_t *output, + ptrdiff_t out_pitch) +{ + __m128i p7_o, p6_o, p5_o, p4_o, p3_o, p2_o, p1_o, p0_o; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + ptrdiff_t out_pitch2 = out_pitch << 1; + ptrdiff_t out_pitch3 = out_pitch2 + out_pitch; + ptrdiff_t out_pitch4 = out_pitch2 << 1; + + DUP4_ARG2(__lsx_vld, input, 0, input, 16, input, 32, input, 48, + p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, input, 64, input, 80, input, 96, input, 112, + p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, input, 128, input, 144, input, 160, input, 176, + q0, q1, q2, q3); + DUP4_ARG2(__lsx_vld, input, 192, input, 208, input, 224, input, 240, + q4, q5, q6, q7); + LSX_TRANSPOSE16x8_B(p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, + q6, q7, p7_o, p6_o, p5_o, p4_o, p3_o, p2_o, p1_o, p0_o); + LSX_ST_8(p7_o, p6_o, p5_o, p4_o, p3_o, p2_o, p1_o, p0_o, + output, out_pitch, out_pitch2, out_pitch3, out_pitch4); +} + +static void vp9_transpose_16x16(uint8_t *input, int32_t in_stride, + uint8_t *output, int32_t out_stride) +{ + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i row8, row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp4, tmp5, tmp6, tmp7; + __m128i tmp2, tmp3; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + int32_t in_stride2 = in_stride << 1; + int32_t in_stride3 = in_stride2 + in_stride; + int32_t in_stride4 = in_stride2 << 1; + int32_t out_stride2 = out_stride << 1; + int32_t out_stride3 = out_stride2 + out_stride; + int32_t out_stride4 = out_stride2 << 1; + + LSX_LD_8(input, in_stride, in_stride2, in_stride3, in_stride4, + row0, row1, row2, row3, row4, row5, row6, row7); + input += in_stride4; + LSX_LD_8(input, in_stride, in_stride2, in_stride3, in_stride4, + row8, row9, row10, row11, row12, row13, row14, row15); + + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p7, p6, p5, p4, p3, p2, p1, p0); + + /* transpose 16x8 matrix into 8x16 */ + /* total 8 intermediate register and 32 instructions */ + q7 = __lsx_vpackod_d(row8, row0); + q6 = __lsx_vpackod_d(row9, row1); + q5 = __lsx_vpackod_d(row10, row2); + q4 = __lsx_vpackod_d(row11, row3); + q3 = __lsx_vpackod_d(row12, row4); + q2 = __lsx_vpackod_d(row13, row5); + q1 = __lsx_vpackod_d(row14, row6); + q0 = __lsx_vpackod_d(row15, row7); + + DUP2_ARG2(__lsx_vpackev_b, q6, q7, q4, q5, tmp0, tmp1); + DUP2_ARG2(__lsx_vpackod_b, q6, q7, q4, q5, tmp4, tmp5); + + DUP2_ARG2(__lsx_vpackev_b, q2, q3, q0, q1, q5, q7); + DUP2_ARG2(__lsx_vpackod_b, q2, q3, q0, q1, tmp6, tmp7); + + DUP2_ARG2(__lsx_vpackev_h, tmp1, tmp0, q7, q5, tmp2, tmp3); + q0 = __lsx_vpackev_w(tmp3, tmp2); + q4 = __lsx_vpackod_w(tmp3, tmp2); + + tmp2 = __lsx_vpackod_h(tmp1, tmp0); + tmp3 = __lsx_vpackod_h(q7, q5); + q2 = __lsx_vpackev_w(tmp3, tmp2); + q6 = __lsx_vpackod_w(tmp3, tmp2); + + DUP2_ARG2(__lsx_vpackev_h, tmp5, tmp4, tmp7, tmp6, tmp2, tmp3); + q1 = __lsx_vpackev_w(tmp3, tmp2); + q5 = __lsx_vpackod_w(tmp3, tmp2); + + tmp2 = __lsx_vpackod_h(tmp5, tmp4); + tmp3 = __lsx_vpackod_h(tmp7, tmp6); + q3 = __lsx_vpackev_w(tmp3, tmp2); + q7 = __lsx_vpackod_w(tmp3, tmp2); + + LSX_ST_8(p7, p6, p5, p4, p3, p2, p1, p0, output, out_stride, + out_stride2, out_stride3, out_stride4); + output += out_stride4; + LSX_ST_8(q0, q1, q2, q3, q4, q5, q6, q7, output, out_stride, + out_stride2, out_stride3, out_stride4); +} + +static int32_t vp9_vt_lpf_t4_and_t8_8w(uint8_t *src, uint8_t *filter48, + uint8_t *src_org, int32_t pitch_org, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i vec0, vec1, vec2, vec3; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vld, src, -64, src, -48, src, -32, src, -16, + p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + + src_org -= 2; + __lsx_vstelm_w(vec2, src_org, 0, 0); + src_org += pitch_org; + __lsx_vstelm_w(vec2, src_org, 0, 1); + src_org += pitch_org; + __lsx_vstelm_w(vec2, src_org, 0, 2); + src_org += pitch_org; + __lsx_vstelm_w(vec2, src_org, 0, 3); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 0); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 1); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 2); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 3); + return 1; + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + /* convert 16 bit output data into 8 bit */ + p2_l = __lsx_vpickev_b(p2_filt8_l, p2_filt8_l); + p1_l = __lsx_vpickev_b(p1_filt8_l, p1_filt8_l); + p0_l = __lsx_vpickev_b(p0_filt8_l, p0_filt8_l); + q0_l = __lsx_vpickev_b(q0_filt8_l, q0_filt8_l); + q1_l = __lsx_vpickev_b(q1_filt8_l, q1_filt8_l); + q2_l = __lsx_vpickev_b(q2_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_l, flat); + + __lsx_vst(p2_out, filter48, 0); + __lsx_vst(p1_out, filter48, 16); + __lsx_vst(p0_out, filter48, 32); + __lsx_vst(q0_out, filter48, 48); + __lsx_vst(q1_out, filter48, 64); + __lsx_vst(q2_out, filter48, 80); + __lsx_vst(flat, filter48, 96); + + return 0; + } +} + +static int32_t vp9_vt_lpf_t16_8w(uint8_t *dst, uint8_t *dst_org, + ptrdiff_t stride, + uint8_t *filter48) +{ + __m128i zero = __lsx_vldi(0); + __m128i filter8, flat, flat2; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + v8u16 p7_l_in, p6_l_in, p5_l_in, p4_l_in; + v8u16 p3_l_in, p2_l_in, p1_l_in, p0_l_in; + v8u16 q7_l_in, q6_l_in, q5_l_in, q4_l_in; + v8u16 q3_l_in, q2_l_in, q1_l_in, q0_l_in; + v8u16 tmp0_l, tmp1_l; + __m128i out_l; + uint8_t *dst_tmp = dst - 128; + + /* load vector elements */ + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, + dst_tmp, 48, p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, dst_tmp, 64, dst_tmp, 80, dst_tmp, 96, + dst_tmp, 112, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst, 16, dst, 32, dst, 48, q0, q1, q2, q3); + DUP4_ARG2(__lsx_vld, dst, 64, dst, 80, dst, 96, dst, 112, q4, q5, q6, q7); + + flat = __lsx_vld(filter48, 96); + + + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + __m128i vec0, vec1, vec2, vec3, vec4; + + DUP4_ARG2(__lsx_vld, filter48, 0, filter48, 16, filter48, 32, + filter48, 48, p2, p1, p0, q0); + DUP2_ARG2(__lsx_vld, filter48, 64, filter48, 80, q1, q2); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + + dst_org -= 3; + __lsx_vstelm_w(vec3, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 0); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 1); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 2); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 3); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 4); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 5); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 6); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 7); + return 1; + } else { + dst -= 7 * 16; + + p7_l_in = (v8u16)__lsx_vilvl_b(zero, p7); + p6_l_in = (v8u16)__lsx_vilvl_b(zero, p6); + p5_l_in = (v8u16)__lsx_vilvl_b(zero, p5); + p4_l_in = (v8u16)__lsx_vilvl_b(zero, p4); + p3_l_in = (v8u16)__lsx_vilvl_b(zero, p3); + p2_l_in = (v8u16)__lsx_vilvl_b(zero, p2); + p1_l_in = (v8u16)__lsx_vilvl_b(zero, p1); + p0_l_in = (v8u16)__lsx_vilvl_b(zero, p0); + q0_l_in = (v8u16)__lsx_vilvl_b(zero, q0); + + tmp0_l = p7_l_in << 3; + tmp0_l -= p7_l_in; + tmp0_l += p6_l_in; + tmp0_l += q0_l_in; + tmp1_l = p6_l_in + p5_l_in; + tmp1_l += p4_l_in; + tmp1_l += p3_l_in; + tmp1_l += p2_l_in; + tmp1_l += p1_l_in; + tmp1_l += p0_l_in; + tmp1_l += tmp0_l; + + out_l =__lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l =__lsx_vpickev_b(out_l, out_l); + p6 = __lsx_vbitsel_v(p6, out_l, flat2); + __lsx_vstelm_d(p6, dst, 0, 0); + dst += 16; + + /* p5 */ + q1_l_in = (v8u16)__lsx_vilvl_b(zero, q1); + tmp0_l = p5_l_in - p6_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + p5 = __lsx_vbitsel_v(p5, out_l, flat2); + __lsx_vstelm_d(p5, dst, 0, 0); + dst += 16; + + /* p4 */ + q2_l_in = (v8u16)__lsx_vilvl_b(zero, q2); + tmp0_l = p4_l_in - p5_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + p4 = __lsx_vbitsel_v(p4, out_l, flat2); + __lsx_vstelm_d(p4, dst, 0, 0); + dst += 16; + + /* p3 */ + q3_l_in = (v8u16)__lsx_vilvl_b(zero, q3); + tmp0_l = p3_l_in - p4_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + p3 = __lsx_vbitsel_v(p3, out_l, flat2); + __lsx_vstelm_d(p3, dst, 0, 0); + dst += 16; + + /* p2 */ + q4_l_in = (v8u16)__lsx_vilvl_b(zero, q4); + filter8 = __lsx_vld(filter48, 0); + tmp0_l = p2_l_in - p3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* p1 */ + q5_l_in = (v8u16)__lsx_vilvl_b(zero, q5); + filter8 = __lsx_vld(filter48, 16); + tmp0_l = p1_l_in - p2_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* p0 */ + q6_l_in = (v8u16)__lsx_vilvl_b(zero, q6); + filter8 = __lsx_vld(filter48, 32); + tmp0_l = p0_l_in - p1_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q0 */ + q7_l_in = (v8u16)__lsx_vilvl_b(zero, q7); + filter8 = __lsx_vld(filter48, 48); + tmp0_l = q7_l_in - p0_l_in; + tmp0_l += q0_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((v8i16) tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q1 */ + filter8 = __lsx_vld(filter48, 64); + tmp0_l = q7_l_in - q0_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p6_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q2 */ + filter8 = __lsx_vld(filter48, 80); + tmp0_l = q7_l_in - q1_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p5_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q3 */ + tmp0_l = q7_l_in - q2_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p4_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q3 = __lsx_vbitsel_v(q3, out_l, flat2); + __lsx_vstelm_d(q3, dst, 0, 0); + dst += 16; + + /* q4 */ + tmp0_l = q7_l_in - q3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p3_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q4 = __lsx_vbitsel_v(q4, out_l, flat2); + __lsx_vstelm_d(q4, dst, 0, 0); + dst += 16; + + /* q5 */ + tmp0_l = q7_l_in - q4_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p2_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q5 = __lsx_vbitsel_v(q5, out_l, flat2); + __lsx_vstelm_d(q5, dst, 0, 0); + dst += 16; + + /* q6 */ + tmp0_l = q7_l_in - q5_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p1_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q6 = __lsx_vbitsel_v(q6, out_l, flat2); + __lsx_vstelm_d(q6, dst, 0, 0); + + return 0; + } +} + +void ff_loop_filter_h_16_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + uint8_t early_exit = 0; + uint8_t transposed_input[16 * 24] __attribute__ ((aligned(16))); + uint8_t *filter48 = &transposed_input[16 * 16]; + + vp9_transpose_16x8_to_8x16(dst - 8, stride, transposed_input); + + early_exit = vp9_vt_lpf_t4_and_t8_8w((transposed_input + 16 * 8), + &filter48[0], dst, stride, + b_limit_ptr, limit_ptr, thresh_ptr); + + if (0 == early_exit) { + early_exit = vp9_vt_lpf_t16_8w((transposed_input + 16 * 8), dst, stride, + &filter48[0]); + + if (0 == early_exit) { + vp9_transpose_8x16_to_16x8(transposed_input, dst - 8, stride); + } + } +} + +static int32_t vp9_vt_lpf_t4_and_t8_16w(uint8_t *dst, uint8_t *filter48, + uint8_t *dst_org, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i vec0, vec1, vec2, vec3, vec4, vec5; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vld, dst, -64, dst, -48, dst, -32, dst, -16, + p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst, 16, dst, 32, dst, 48, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst_org -= 2; + __lsx_vstelm_w(vec2, dst_org, 0, 0); + __lsx_vstelm_w(vec2, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec2, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst_org + stride3, 0, 3); + dst_org += stride4; + __lsx_vstelm_w(vec3, dst_org, 0, 0); + __lsx_vstelm_w(vec3, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec3, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst_org + stride3, 0, 3); + dst_org += stride4; + __lsx_vstelm_w(vec4, dst_org, 0, 0); + __lsx_vstelm_w(vec4, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec4, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst_org + stride3, 0, 3); + dst_org += stride4; + __lsx_vstelm_w(vec5, dst_org, 0, 0); + __lsx_vstelm_w(vec5, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec5, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst_org + stride3, 0, 3); + + return 1; + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, + q0_filt8_l, p2_filt8_l, p1_filt8_l, p0_filt8_l, + q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + __lsx_vst(p2_out, filter48, 0); + __lsx_vst(p1_out, filter48, 16); + __lsx_vst(p0_out, filter48, 32); + __lsx_vst(q0_out, filter48, 48); + __lsx_vst(q1_out, filter48, 64); + __lsx_vst(q2_out, filter48, 80); + __lsx_vst(flat, filter48, 96); + + return 0; + } +} + +static int32_t vp9_vt_lpf_t16_16w(uint8_t *dst, uint8_t *dst_org, + ptrdiff_t stride, + uint8_t *filter48) +{ + __m128i zero = __lsx_vldi(0); + __m128i flat, flat2, filter8; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + v8u16 p7_l_in, p6_l_in, p5_l_in, p4_l_in; + v8u16 p3_l_in, p2_l_in, p1_l_in, p0_l_in; + v8u16 q7_l_in, q6_l_in, q5_l_in, q4_l_in; + v8u16 q3_l_in, q2_l_in, q1_l_in, q0_l_in; + v8u16 p7_h_in, p6_h_in, p5_h_in, p4_h_in; + v8u16 p3_h_in, p2_h_in, p1_h_in, p0_h_in; + v8u16 q7_h_in, q6_h_in, q5_h_in, q4_h_in; + v8u16 q3_h_in, q2_h_in, q1_h_in, q0_h_in; + v8u16 tmp0_l, tmp1_l, tmp0_h, tmp1_h; + __m128i out_l, out_h; + uint8_t *dst_tmp = dst - 128; + + flat = __lsx_vld(filter48, 96); + + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, + dst_tmp, 48, p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, dst_tmp, 64, dst_tmp, 80, dst_tmp, 96, + dst_tmp, 112, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst, 16, dst, 32, dst, 48, q0, q1, q2, q3); + DUP4_ARG2(__lsx_vld, dst, 64, dst, 80, dst, 96, dst, 112, q4, q5, q6, q7); + + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + + DUP4_ARG2(__lsx_vld, filter48, 0, filter48, 16, filter48, 32, + filter48, 48, p2, p1, p0, q0); + DUP2_ARG2(__lsx_vld, filter48, 64, filter48, 80, q1, q2); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst_org -= 3; + __lsx_vstelm_w(vec3, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 0); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 1); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 2); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 3); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 4); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 5); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 6); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 7); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 0); + __lsx_vstelm_h(vec5, dst_org, 4, 0); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 1); + __lsx_vstelm_h(vec5, dst_org, 4, 1); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 2); + __lsx_vstelm_h(vec5, dst_org, 4, 2); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 3); + __lsx_vstelm_h(vec5, dst_org, 4, 3); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 0); + __lsx_vstelm_h(vec5, dst_org, 4, 4); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 1); + __lsx_vstelm_h(vec5, dst_org, 4, 5); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 2); + __lsx_vstelm_h(vec5, dst_org, 4, 6); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 3); + __lsx_vstelm_h(vec5, dst_org, 4, 7); + + return 1; + } else { + dst -= 7 * 16; + + p7_l_in = (v8u16)__lsx_vilvl_b(zero, p7); + p6_l_in = (v8u16)__lsx_vilvl_b(zero, p6); + p5_l_in = (v8u16)__lsx_vilvl_b(zero, p5); + p4_l_in = (v8u16)__lsx_vilvl_b(zero, p4); + p3_l_in = (v8u16)__lsx_vilvl_b(zero, p3); + p2_l_in = (v8u16)__lsx_vilvl_b(zero, p2); + p1_l_in = (v8u16)__lsx_vilvl_b(zero, p1); + p0_l_in = (v8u16)__lsx_vilvl_b(zero, p0); + q0_l_in = (v8u16)__lsx_vilvl_b(zero, q0); + + tmp0_l = p7_l_in << 3; + tmp0_l -= p7_l_in; + tmp0_l += p6_l_in; + tmp0_l += q0_l_in; + tmp1_l = p6_l_in + p5_l_in; + tmp1_l += p4_l_in; + tmp1_l += p3_l_in; + tmp1_l += p2_l_in; + tmp1_l += p1_l_in; + tmp1_l += p0_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + p7_h_in = (v8u16)__lsx_vilvh_b(zero, p7); + p6_h_in = (v8u16)__lsx_vilvh_b(zero, p6); + p5_h_in = (v8u16)__lsx_vilvh_b(zero, p5); + p4_h_in = (v8u16)__lsx_vilvh_b(zero, p4); + p3_h_in = (v8u16)__lsx_vilvh_b(zero, p3); + p2_h_in = (v8u16)__lsx_vilvh_b(zero, p2); + p1_h_in = (v8u16)__lsx_vilvh_b(zero, p1); + p0_h_in = (v8u16)__lsx_vilvh_b(zero, p0); + q0_h_in = (v8u16)__lsx_vilvh_b(zero, q0); + + tmp0_h = p7_h_in << 3; + tmp0_h -= p7_h_in; + tmp0_h += p6_h_in; + tmp0_h += q0_h_in; + tmp1_h = p6_h_in + p5_h_in; + tmp1_h += p4_h_in; + tmp1_h += p3_h_in; + tmp1_h += p2_h_in; + tmp1_h += p1_h_in; + tmp1_h += p0_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p6 = __lsx_vbitsel_v(p6, out_l, flat2); + __lsx_vst(p6, dst, 0); + + /* p5 */ + q1_l_in = (v8u16)__lsx_vilvl_b(zero, q1); + tmp0_l = p5_l_in - p6_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q1_h_in = (v8u16)__lsx_vilvh_b(zero, q1); + tmp0_h = p5_h_in - p6_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + p5 = __lsx_vbitsel_v(p5, out_l, flat2); + __lsx_vst(p5, dst, 16); + + /* p4 */ + q2_l_in = (v8u16)__lsx_vilvl_b(zero, q2); + tmp0_l = p4_l_in - p5_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q2_h_in = (v8u16)__lsx_vilvh_b(zero, q2); + tmp0_h = p4_h_in - p5_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + p4 = __lsx_vbitsel_v(p4, out_l, flat2); + __lsx_vst(p4, dst, 16*2); + + /* p3 */ + q3_l_in = (v8u16)__lsx_vilvl_b(zero, q3); + tmp0_l = p3_l_in - p4_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q3_h_in = (v8u16)__lsx_vilvh_b(zero, q3); + tmp0_h = p3_h_in - p4_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + p3 = __lsx_vbitsel_v(p3, out_l, flat2); + __lsx_vst(p3, dst, 16*3); + + /* p2 */ + q4_l_in = (v8u16)__lsx_vilvl_b(zero, q4); + filter8 = __lsx_vld(filter48, 0); + tmp0_l = p2_l_in - p3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q4_h_in = (v8u16)__lsx_vilvh_b(zero, q4); + tmp0_h = p2_h_in - p3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*4); + + /* p1 */ + q5_l_in = (v8u16)__lsx_vilvl_b(zero, q5); + filter8 = __lsx_vld(filter48, 16); + tmp0_l = p1_l_in - p2_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q5_h_in = (v8u16)__lsx_vilvh_b(zero, q5); + tmp0_h = p1_h_in - p2_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)(tmp1_h), 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*5); + + /* p0 */ + q6_l_in = (v8u16)__lsx_vilvl_b(zero, q6); + filter8 = __lsx_vld(filter48, 32); + tmp0_l = p0_l_in - p1_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q6_h_in = (v8u16)__lsx_vilvh_b(zero, q6); + tmp0_h = p0_h_in - p1_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*6); + + /* q0 */ + q7_l_in = (v8u16)__lsx_vilvl_b(zero, q7); + filter8 = __lsx_vld(filter48, 48); + tmp0_l = q7_l_in - p0_l_in; + tmp0_l += q0_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q7_h_in = (v8u16)__lsx_vilvh_b(zero, q7); + tmp0_h = q7_h_in - p0_h_in; + tmp0_h += q0_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*7); + + /* q1 */ + filter8 = __lsx_vld(filter48, 64); + tmp0_l = q7_l_in - q0_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p6_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q0_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p6_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*8); + + /* q2 */ + filter8 = __lsx_vld(filter48, 80); + tmp0_l = q7_l_in - q1_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p5_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q1_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p5_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*9); + + /* q3 */ + tmp0_l = q7_l_in - q2_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p4_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q2_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p4_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q3 = __lsx_vbitsel_v(q3, out_l, flat2); + __lsx_vst(q3, dst, 16*10); + + /* q4 */ + tmp0_l = q7_l_in - q3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p3_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p3_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q4 = __lsx_vbitsel_v(q4, out_l, flat2); + __lsx_vst(q4, dst, 16*11); + + /* q5 */ + tmp0_l = q7_l_in - q4_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p2_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q4_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p2_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q5 = __lsx_vbitsel_v(q5, out_l, flat2); + __lsx_vst(q5, dst, 16*12); + + /* q6 */ + tmp0_l = q7_l_in - q5_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p1_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q5_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p1_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q6 = __lsx_vbitsel_v(q6, out_l, flat2); + __lsx_vst(q6, dst, 16*13); + + return 0; + } +} + +void ff_loop_filter_h_16_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + uint8_t early_exit = 0; + uint8_t transposed_input[16 * 24] __attribute__ ((aligned(16))); + uint8_t *filter48 = &transposed_input[16 * 16]; + + vp9_transpose_16x16((dst - 8), stride, &transposed_input[0], 16); + + early_exit = vp9_vt_lpf_t4_and_t8_16w((transposed_input + 16 * 8), + &filter48[0], dst, stride, + b_limit_ptr, limit_ptr, thresh_ptr); + + if (0 == early_exit) { + early_exit = vp9_vt_lpf_t16_16w((transposed_input + 16 * 8), dst, + stride, &filter48[0]); + + if (0 == early_exit) { + vp9_transpose_16x16(transposed_input, 16, (dst - 8), stride); + } + } +} diff --git a/libavcodec/loongarch/vp9dsp_init_loongarch.c b/libavcodec/loongarch/vp9dsp_init_loongarch.c index c1e01b4558..e49625ad5f 100644 --- a/libavcodec/loongarch/vp9dsp_init_loongarch.c +++ b/libavcodec/loongarch/vp9dsp_init_loongarch.c @@ -71,6 +71,15 @@ dsp->intra_pred[tx][TOP_DC_PRED] = ff_dc_top_##sz##_lsx; \ dsp->intra_pred[tx][TM_VP8_PRED] = ff_tm_##sz##_lsx; \ +#define init_idct(tx, nm) \ + dsp->itxfm_add[tx][DCT_DCT] = \ + dsp->itxfm_add[tx][ADST_DCT] = \ + dsp->itxfm_add[tx][DCT_ADST] = \ + dsp->itxfm_add[tx][ADST_ADST] = nm##_add_lsx; + +#define init_itxfm(tx, sz) \ + dsp->itxfm_add[tx][DCT_DCT] = ff_idct_idct_##sz##_add_lsx; + av_cold void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp) { int cpu_flags = av_get_cpu_flags(); @@ -86,8 +95,30 @@ av_cold void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp) init_intra_pred1_lsx(TX_32X32, 32x32); init_intra_pred2_lsx(TX_4X4, 4x4); init_intra_pred2_lsx(TX_8X8, 8x8); + init_itxfm(TX_8X8, 8x8); + init_itxfm(TX_16X16, 16x16); + init_idct(TX_32X32, ff_idct_idct_32x32); + dsp->loop_filter_8[0][0] = ff_loop_filter_h_4_8_lsx; + dsp->loop_filter_8[0][1] = ff_loop_filter_v_4_8_lsx; + dsp->loop_filter_8[1][0] = ff_loop_filter_h_8_8_lsx; + dsp->loop_filter_8[1][1] = ff_loop_filter_v_8_8_lsx; + dsp->loop_filter_8[2][0] = ff_loop_filter_h_16_8_lsx; + dsp->loop_filter_8[2][1] = ff_loop_filter_v_16_8_lsx; + + dsp->loop_filter_16[0] = ff_loop_filter_h_16_16_lsx; + dsp->loop_filter_16[1] = ff_loop_filter_v_16_16_lsx; + + dsp->loop_filter_mix2[0][0][0] = ff_loop_filter_h_44_16_lsx; + dsp->loop_filter_mix2[0][0][1] = ff_loop_filter_v_44_16_lsx; + dsp->loop_filter_mix2[0][1][0] = ff_loop_filter_h_48_16_lsx; + dsp->loop_filter_mix2[0][1][1] = ff_loop_filter_v_48_16_lsx; + dsp->loop_filter_mix2[1][0][0] = ff_loop_filter_h_84_16_lsx; + dsp->loop_filter_mix2[1][0][1] = ff_loop_filter_v_84_16_lsx; + dsp->loop_filter_mix2[1][1][0] = ff_loop_filter_h_88_16_lsx; + dsp->loop_filter_mix2[1][1][1] = ff_loop_filter_v_88_16_lsx; } } + #undef init_subpel1 #undef init_subpel2 #undef init_subpel3 @@ -95,3 +126,5 @@ av_cold void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp) #undef init_fpel #undef init_intra_pred1_lsx #undef init_intra_pred2_lsx +#undef init_idct +#undef init_itxfm diff --git a/libavcodec/loongarch/vp9dsp_loongarch.h b/libavcodec/loongarch/vp9dsp_loongarch.h index b469326fdc..3cc918a18c 100644 --- a/libavcodec/loongarch/vp9dsp_loongarch.h +++ b/libavcodec/loongarch/vp9dsp_loongarch.h @@ -140,5 +140,43 @@ void ff_tm_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, const uint8_t *top); void ff_tm_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, const uint8_t *top); +void ff_loop_filter_h_16_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_16_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_4_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_4_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_44_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_44_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_8_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_8_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_88_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_88_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_84_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_84_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_48_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_48_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_16_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_16_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_idct_idct_8x8_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob); +void ff_idct_idct_16x16_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob); +void ff_idct_idct_32x32_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob); #endif /* AVCODEC_LOONGARCH_VP9DSP_LOONGARCH_H */ From 60ead5cd68586d25bd6a0c285907f72b8a2534bf Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Sat, 18 Dec 2021 22:27:57 +0800 Subject: [PATCH 611/894] avcodec: [loongarch] Optimize vc1dsp with LASX. ./ffmpeg -i 11_wmv3_720p_24fps_7Mbps.wmv -f rawvideo -y /dev/null -an before:131fps after :229fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 2 + libavcodec/loongarch/vc1dsp_init_loongarch.c | 67 ++ libavcodec/loongarch/vc1dsp_lasx.c | 1005 ++++++++++++++++++ libavcodec/loongarch/vc1dsp_loongarch.h | 79 ++ libavcodec/vc1dsp.c | 2 + libavcodec/vc1dsp.h | 1 + 6 files changed, 1156 insertions(+) create mode 100644 libavcodec/loongarch/vc1dsp_init_loongarch.c create mode 100644 libavcodec/loongarch/vc1dsp_lasx.c create mode 100644 libavcodec/loongarch/vc1dsp_loongarch.h diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 4b83f20e92..baf5f92e84 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -4,12 +4,14 @@ OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch.o OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o +OBJS-$(CONFIG_VC1DSP) += loongarch/vc1dsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ loongarch/h264idct_lasx.o \ loongarch/h264_deblock_lasx.o LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o +LASX-OBJS-$(CONFIG_VC1_DECODER) += loongarch/vc1dsp_lasx.o LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ loongarch/vp8_lpf_lsx.o LSX-OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9_mc_lsx.o \ diff --git a/libavcodec/loongarch/vc1dsp_init_loongarch.c b/libavcodec/loongarch/vc1dsp_init_loongarch.c new file mode 100644 index 0000000000..e72a4a3203 --- /dev/null +++ b/libavcodec/loongarch/vc1dsp_init_loongarch.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/vc1dsp.h" +#include "vc1dsp_loongarch.h" + +#define FN_ASSIGN(OP, X, Y, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[1][X+4*Y] = ff_##OP##vc1_mspel_mc##X##Y##INSN; \ + dsp->OP##vc1_mspel_pixels_tab[0][X+4*Y] = ff_##OP##vc1_mspel_mc##X##Y##_16##INSN + +#define FN_ASSIGN_V(OP, Y, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[0][4*Y] = ff_##OP##vc1_mspel_mc0##Y##_16##INSN + +#define FN_ASSIGN_H(OP, X, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[0][X] = ff_##OP##vc1_mspel_mc##X##0_16##INSN + +av_cold void ff_vc1dsp_init_loongarch(VC1DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_lasx; + dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_lasx; + dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_lasx; + dsp->vc1_inv_trans_4x4 = ff_vc1_inv_trans_4x4_lasx; + dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_lasx; + dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_lasx; + dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_lasx; + dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_lasx; + FN_ASSIGN(put_, 1, 1, _lasx); + FN_ASSIGN(put_, 1, 2, _lasx); + FN_ASSIGN(put_, 1, 3, _lasx); + FN_ASSIGN(put_, 2, 1, _lasx); + FN_ASSIGN(put_, 2, 2, _lasx); + FN_ASSIGN(put_, 2, 3, _lasx); + FN_ASSIGN(put_, 3, 1, _lasx); + FN_ASSIGN(put_, 3, 2, _lasx); + FN_ASSIGN(put_, 3, 3, _lasx); + FN_ASSIGN_V(put_, 1, _lasx); + FN_ASSIGN_V(put_, 2, _lasx); + FN_ASSIGN_V(put_, 3, _lasx); + FN_ASSIGN_H(put_, 1, _lasx); + FN_ASSIGN_H(put_, 2, _lasx); + FN_ASSIGN_H(put_, 3, _lasx); + dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_no_rnd_vc1_chroma_mc8_lasx; + } +} diff --git a/libavcodec/loongarch/vc1dsp_lasx.c b/libavcodec/loongarch/vc1dsp_lasx.c new file mode 100644 index 0000000000..40b8668f2b --- /dev/null +++ b/libavcodec/loongarch/vc1dsp_lasx.c @@ -0,0 +1,1005 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vc1dsp_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +void ff_vc1_inv_trans_8x8_lasx(int16_t block[64]) +{ + int32_t con_4 = 4; + int32_t con_64 = 64; + __m256i in0, in1, in2, in3; + __m256i temp0, temp1, temp2, temp3, t1, t2, t3, t4, t5, t6, t7, t8; + __m256i const_1 = {0x000c000c000c000c, 0x000c000c000c000c, + 0x000c000c000c000c, 0x000c000c000c000c}; + __m256i const_2 = {0xfff4000cfff4000c, 0xfff4000cfff4000c, + 0xfff4000cfff4000c, 0xfff4000cfff4000c}; + __m256i const_3 = {0x0006001000060010, 0x0006001000060010, + 0x0006001000060010, 0x0006001000060010}; + __m256i const_4 = {0xfff00006fff00006, 0xfff00006fff00006, + 0xfff00006fff00006, 0xfff00006fff00006}; + __m256i const_5 = {0x000f0010000f0010, 0x000f0010000f0010, + 0x000f0010000f0010, 0x000f0010000f0010}; + __m256i const_6 = {0x0004000900040009, 0x0004000900040009, + 0x0004000900040009, 0x0004000900040009}; + __m256i const_7 = {0xfffc000ffffc000f, 0xfffc000ffffc000f, + 0xfffc000ffffc000f, 0xfffc000ffffc000f}; + __m256i const_8 = {0xfff7fff0fff7fff0, 0xfff7fff0fff7fff0, + 0xfff7fff0fff7fff0, 0xfff7fff0fff7fff0}; + __m256i const_9 = {0xfff00009fff00009, 0xfff00009fff00009, + 0xfff00009fff00009, 0xfff00009fff00009}; + __m256i const_10 = {0x000f0004000f0004, 0x000f0004000f0004, + 0x000f0004000f0004, 0x000f0004000f0004}; + __m256i const_11 = {0xfff70004fff70004, 0xfff70004fff70004, + 0xfff70004fff70004, 0xfff70004fff70004}; + __m256i const_12 = {0xfff0000ffff0000f, 0xfff0000ffff0000f, + 0xfff0000ffff0000f, 0xfff0000ffff0000f}; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + /* first loops */ + DUP2_ARG2(__lasx_xvilvl_h, in2, in0, in3, in1, temp0, temp1); + t2 = __lasx_xvreplgr2vr_w(con_4); + DUP2_ARG3(__lasx_xvdp2add_w_h, t2, temp0, const_1, t2, temp0, + const_2, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_3, temp1, const_4, t3, t4); + + t5 = __lasx_xvadd_w(t1, t3); + t6 = __lasx_xvadd_w(t2, t4); + t7 = __lasx_xvsub_w(t2, t4); + t8 = __lasx_xvsub_w(t1, t3); + + DUP2_ARG2(__lasx_xvilvh_h, in1, in0, in3, in2, temp0, temp1); + temp2 = __lasx_xvdp2_w_h(const_5, temp0); + t1 = __lasx_xvdp2add_w_h(temp2, temp1, const_6); + temp2 = __lasx_xvdp2_w_h(const_7, temp0); + t2 = __lasx_xvdp2add_w_h(temp2, temp1, const_8); + temp2 = __lasx_xvdp2_w_h(const_9, temp0); + t3 = __lasx_xvdp2add_w_h(temp2, temp1, const_10); + temp2 = __lasx_xvdp2_w_h(const_11, temp0); + t4 = __lasx_xvdp2add_w_h(temp2, temp1, const_12); + + DUP4_ARG2(__lasx_xvadd_w, t1, t5, t6, t2, t7, t3, t8, t4, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvsub_w, t8, t4, t7, t3, t6, t2, t5, t1, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 3, temp1, 3, temp2, 3, temp3, 3, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvsrai_w, in0, 3, in1, 3, in2, 3, in3, 3, + in0, in1, in2, in3); + + /* second loops */ + DUP4_ARG2(__lasx_xvpackev_h, temp1, temp0, temp3, temp2, in1, in0, + in3, in2, temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvilvl_w, temp1, temp0, temp3, temp2, t1, t3); + DUP2_ARG2(__lasx_xvilvh_w, temp1, temp0, temp3, temp2, t2, t4); + DUP4_ARG3(__lasx_xvpermi_q, t3, t1, 0x20, t3, t1, 0x31, t4, t2, 0x20, + t4, t2, 0x31, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_h, in1, in0, in3, in2, temp0, temp1); + t3 = __lasx_xvreplgr2vr_w(con_64); + DUP2_ARG3(__lasx_xvdp2add_w_h, t3, temp0, const_1, t3, temp0, + const_2, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_3, temp1, const_4, t3, t4); + + t5 = __lasx_xvadd_w(t1, t3); + t6 = __lasx_xvadd_w(t2, t4); + t7 = __lasx_xvsub_w(t2, t4); + t8 = __lasx_xvsub_w(t1, t3); + + DUP2_ARG2(__lasx_xvilvh_h, in2, in0, in3, in1, temp0, temp1); + temp2 = __lasx_xvdp2_w_h(const_5, temp0); + t1 = __lasx_xvdp2add_w_h(temp2, temp1, const_6); + temp2 = __lasx_xvdp2_w_h(const_7, temp0); + t2 = __lasx_xvdp2add_w_h(temp2, temp1, const_8); + temp2 = __lasx_xvdp2_w_h(const_9, temp0); + t3 = __lasx_xvdp2add_w_h(temp2, temp1, const_10); + temp2 = __lasx_xvdp2_w_h(const_11, temp0); + t4 = __lasx_xvdp2add_w_h(temp2, temp1, const_12); + + DUP4_ARG2(__lasx_xvadd_w, t5, t1, t6, t2, t7, t3, t8, t4, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvsub_w, t8, t4, t7, t3, t6, t2, t5, t1, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvaddi_wu, in0, 1, in1, 1, in2, 1, in3, 1, + in0, in1, in2, in3); + DUP4_ARG3(__lasx_xvsrani_h_w, temp1, temp0, 7, temp3, temp2, 7, + in1, in0, 7, in3, in2, 7, t1, t2, t3, t4); + DUP4_ARG2(__lasx_xvpermi_d, t1, 0xD8, t2, 0xD8, t3, 0xD8, t4, 0xD8, + in0, in1, in2, in3); + __lasx_xvst(in0, block, 0); + __lasx_xvst(in1, block, 32); + __lasx_xvst(in2, block, 64); + __lasx_xvst(in3, block, 96); +} + +void ff_vc1_inv_trans_8x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + uint8_t *dst = dest + (stride2 << 1); + __m256i in0, in1, in2, in3, in4, in5, in6, in7; + __m256i const_dc, temp0, temp1, temp2, temp3; + __m256i reg0, reg1, reg2, reg3; + + dc = (3 * dc + 1) >> 1; + dc = (3 * dc + 16) >> 5; + + const_dc = __lasx_xvreplgr2vr_h(dc); + DUP4_ARG2(__lasx_xvldrepl_d, dest, 0, dest + stride, 0, dest + stride2, + 0, dest + stride3, 0, in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvldrepl_d, dst, 0, dst + stride, 0, dst + stride2, + 0, dst + stride3, 0, in4, in5, in6, in7); + + DUP4_ARG2(__lasx_xvilvl_d, in1, in0, in3, in2, in5, in4, in7, in6, + temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_vext2xv_hu_bu, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + + DUP4_ARG2(__lasx_xvadd_h, temp0, const_dc, temp1, const_dc, temp2, + const_dc, temp3, const_dc, reg0, reg1, reg2, reg3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, reg1, reg0, 0, reg3, reg2, 0, + temp0, temp1); + __lasx_xvstelm_d(temp0, dest, 0, 0); + __lasx_xvstelm_d(temp0, dest + stride, 0, 2); + __lasx_xvstelm_d(temp0, dest + stride2, 0, 1); + __lasx_xvstelm_d(temp0, dest + stride3, 0, 3); + __lasx_xvstelm_d(temp1, dst, 0, 0); + __lasx_xvstelm_d(temp1, dst + stride, 0, 2); + __lasx_xvstelm_d(temp1, dst + stride2, 0, 1); + __lasx_xvstelm_d(temp1, dst + stride3, 0, 3); +} + +void ff_vc1_inv_trans_8x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + __m256i shift = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + __m256i const_64 = {0x0000004000000040, 0x0000004000000040, + 0x0000004000000040, 0x0000004000000040}; + __m256i const_1 = {0x00060010000C000C, 0x00060010000C000C, + 0x00060010000C000C, 0x00060010000C000C}; + __m256i const_2 = {0xFFF00006FFF4000C, 0xFFF00006FFF4000C, + 0xFFF00006FFF4000C, 0xFFF00006FFF4000C}; + __m256i const_3 = {0x0004000F00090010, 0x0004000F00090010, + 0x0004000F00090010, 0x0004000F00090010}; + __m256i const_4 = {0xFFF7FFFCFFF0000F, 0xFFF7FFFCFFF0000F, + 0xFFF7FFFCFFF0000F, 0xFFF7FFFCFFF0000F}; + __m256i const_5 = {0x000FFFF000040009, 0x000FFFF000040009, + 0x000FFFF000040009, 0x000FFFF000040009}; + __m256i const_6 = {0xFFF0FFF7000F0004, 0xFFF0FFF7000F0004, + 0xFFF0FFF7000F0004, 0xFFF0FFF7000F0004}; + __m256i const_7 = {0x0000000000000004, 0x0000000000000004, + 0x0000000000000004, 0x0000000000000004}; + __m256i const_8 = {0x0011001100110011, 0x0011001100110011, + 0x0011001100110011, 0x0011001100110011}; + __m256i const_9 = {0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011, + 0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011}; + __m256i const_10 = {0x000A0016000A0016, 0x000A0016000A0016, + 0x000A0016000A0016, 0x000A0016000A0016}; + __m256i const_11 = {0x0016FFF60016FFF6, 0x0016FFF60016FFF6, + 0x0016FFF60016FFF6, 0x0016FFF60016FFF6}; + __m256i in0, in1; + __m256i temp0, temp1, temp2, temp3, t1, t2, t3, t4; + + DUP2_ARG2(__lasx_xvld, block, 0, block, 32, in0, in1); + /* first loops */ + temp0 = __lasx_xvpermi_d(in0, 0xB1); + temp1 = __lasx_xvpermi_d(in1, 0xB1); + DUP2_ARG2(__lasx_xvilvl_h, temp0, in0, temp1, in1, temp0, temp1); + temp2 = __lasx_xvpickev_w(temp1, temp0); + temp3 = __lasx_xvpickod_w(temp1, temp0); + + DUP2_ARG2(__lasx_xvdp2_w_h, temp2, const_1, temp2, const_2, temp0, temp1); + t1 = __lasx_xvadd_w(temp0, const_7); + t2 = __lasx_xvadd_w(temp1, const_7); + temp0 = __lasx_xvpickev_w(t2, t1); + temp1 = __lasx_xvpickod_w(t2, t1); + t3 = __lasx_xvadd_w(temp0, temp1); + t4 = __lasx_xvsub_w(temp0, temp1); + t4 = __lasx_xvpermi_d(t4, 0xB1); + + DUP4_ARG2(__lasx_xvdp4_d_h, temp3, const_3, temp3, const_4, temp3, + const_5, temp3, const_6, t1, t2, temp0, temp1); + temp2 = __lasx_xvpickev_w(t2, t1); + temp3 = __lasx_xvpickev_w(temp1, temp0); + + t1 = __lasx_xvadd_w(temp2, t3); + t2 = __lasx_xvadd_w(temp3, t4); + temp0 = __lasx_xvsub_w(t4, temp3); + temp1 = __lasx_xvsub_w(t3, temp2); + /* second loops */ + DUP2_ARG3(__lasx_xvsrani_h_w, t2, t1, 3, temp1, temp0, 3, temp2, temp3); + temp3 = __lasx_xvshuf4i_h(temp3, 0x4E); + temp0 = __lasx_xvpermi_q(temp3, temp2, 0x20); + temp1 = __lasx_xvpermi_q(temp3, temp2, 0x31); + DUP2_ARG3(__lasx_xvdp2add_w_h, const_64, temp0, const_8, const_64, temp0, + const_9, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_10, temp1, const_11, t3, t4); + temp0 = __lasx_xvadd_w(t1, t3); + temp1 = __lasx_xvsub_w(t2, t4); + temp2 = __lasx_xvadd_w(t2, t4); + temp3 = __lasx_xvsub_w(t1, t3); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 7, temp1, 7, temp2, 7, temp3, 7, + t1, t2, t3, t4); + + temp0 = __lasx_xvldrepl_d(dest, 0); + DUP4_ARG2(__lasx_xvldrepl_d, dest, 0, dest + stride, 0, dest + stride2, 0, + dest + stride3, 0, temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_vext2xv_wu_bu, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvadd_w, temp0, t1, temp1, t2, temp2, t3, temp3, t4, + t1, t2, t3, t4); + DUP4_ARG1(__lasx_xvclip255_w, t1, t2, t3, t4, t1, t2, t3, t4); + DUP2_ARG2(__lasx_xvpickev_h, t2, t1, t4, t3, temp0, temp1); + temp2 = __lasx_xvpickev_b(temp1, temp0); + temp0 = __lasx_xvperm_w(temp2, shift); + __lasx_xvstelm_d(temp0, dest, 0, 0); + __lasx_xvstelm_d(temp0, dest + stride, 0, 1); + __lasx_xvstelm_d(temp0, dest + stride2, 0, 2); + __lasx_xvstelm_d(temp0, dest + stride3, 0, 3); +} + +void ff_vc1_inv_trans_8x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + __m256i in0, in1, in2, in3; + __m256i const_dc, temp0, temp1, reg0, reg1; + + dc = (3 * dc + 1) >> 1; + dc = (17 * dc + 64) >> 7; + const_dc = __lasx_xvreplgr2vr_h(dc); + + DUP4_ARG2(__lasx_xvldrepl_d, dest, 0, dest + stride, 0, dest + stride2, + 0, dest + stride3, 0, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_d, in1, in0, in3, in2, temp0, temp1); + DUP2_ARG1(__lasx_vext2xv_hu_bu, temp0, temp1, temp0, temp1); + DUP2_ARG2(__lasx_xvadd_h, temp0, const_dc, temp1, const_dc, reg0, reg1); + temp0 = __lasx_xvssrarni_bu_h(reg1, reg0, 0); + __lasx_xvstelm_d(temp0, dest, 0, 0); + __lasx_xvstelm_d(temp0, dest + stride, 0, 2); + __lasx_xvstelm_d(temp0, dest + stride2, 0, 1); + __lasx_xvstelm_d(temp0, dest + stride3, 0, 3); +} + +void ff_vc1_inv_trans_4x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + uint8_t *dst = dest + (stride2 << 1); + __m256i in0, in1, in2, in3, in4, in5, in6, in7; + __m256i const_dc, temp0, temp1, temp2, temp3, reg0, reg1; + + dc = (17 * dc + 4) >> 3; + dc = (12 * dc + 64) >> 7; + const_dc = __lasx_xvreplgr2vr_h(dc); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dest + stride, 0, dest + stride2, + 0, dest + stride3, 0, in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvldrepl_w, dst, 0, dst + stride, 0, dst + stride2, + 0, dst + stride3, 0, in4, in5, in6, in7); + + DUP4_ARG2(__lasx_xvilvl_w, in1, in0, in3, in2, in5, in4, in7, in6, + temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvilvl_d, temp1, temp0, temp3, temp2, reg0, reg1); + DUP2_ARG1(__lasx_vext2xv_hu_bu, reg0, reg1, temp0, temp1); + DUP2_ARG2(__lasx_xvadd_h, temp0, const_dc, temp1, const_dc, reg0, reg1); + temp0 = __lasx_xvssrarni_bu_h(reg1, reg0, 0); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dest + stride, 0, 1); + __lasx_xvstelm_w(temp0, dest + stride2, 0, 4); + __lasx_xvstelm_w(temp0, dest + stride3, 0, 5); + __lasx_xvstelm_w(temp0, dst, 0, 2); + __lasx_xvstelm_w(temp0, dst + stride, 0, 3); + __lasx_xvstelm_w(temp0, dst + stride2, 0, 6); + __lasx_xvstelm_w(temp0, dst + stride3, 0, 7); +} + +void ff_vc1_inv_trans_4x8_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + uint8_t *dst = dest + (stride2 << 1); + __m256i in0, in1, in2, in3; + __m256i temp0, temp1, temp2, temp3, t1, t2, t3, t4; + + __m256i const_1 = {0x0011001100110011, 0x0011001100110011, + 0x0011001100110011, 0x0011001100110011}; + __m256i const_2 = {0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011, + 0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011}; + __m256i const_3 = {0x000A0016000A0016, 0x000A0016000A0016, + 0x000A0016000A0016, 0x000A0016000A0016}; + __m256i const_4 = {0x0016FFF60016FFF6, 0x0016FFF60016FFF6, + 0x0016FFF60016FFF6, 0x0016FFF60016FFF6}; + __m256i const_5 = {0x0000000400000004, 0x0000000400000004, + 0x0000000400000004, 0x0000000400000004}; + __m256i const_6 = {0x0000004000000040, 0x0000004000000040, + 0x0000004000000040, 0x0000004000000040}; + __m256i const_7 = {0x000C000C000C000C, 0X000C000C000C000C, + 0xFFF4000CFFF4000C, 0xFFF4000CFFF4000C}; + __m256i const_8 = {0x0006001000060010, 0x0006001000060010, + 0xFFF00006FFF00006, 0xFFF00006FFF00006}; + __m256i const_9 = {0x0009001000090010, 0x0009001000090010, + 0x0004000F0004000F, 0x0004000F0004000F}; + __m256i const_10 = {0xFFF0000FFFF0000F, 0xFFF0000FFFF0000F, + 0xFFF7FFFCFFF7FFFC, 0xFFF7FFFCFFF7FFFC}; + __m256i const_11 = {0x0004000900040009, 0x0004000900040009, + 0x000FFFF0000FFFF0, 0x000FFFF0000FFFF0}; + __m256i const_12 = {0x000F0004000F0004, 0x000F0004000F0004, + 0xFFF0FFF7FFF0FFF7, 0xFFF0FFF7FFF0FFF7}; + __m256i shift = {0x0000000400000000, 0x0000000600000002, + 0x0000000500000001, 0x0000000700000003}; + + /* first loops */ + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + in0, in1, in2, in3); + in0 = __lasx_xvilvl_d(in1, in0); + in1 = __lasx_xvilvl_d(in3, in2); + temp0 = __lasx_xvpickev_h(in1, in0); + temp1 = __lasx_xvpickod_h(in1, in0); + temp0 = __lasx_xvperm_w(temp0, shift); + temp1 = __lasx_xvperm_w(temp1, shift); + + DUP2_ARG3(__lasx_xvdp2add_w_h, const_5, temp0, const_1, const_5, temp0, + const_2, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_3, temp1, const_4, t3, t4); + + temp0 = __lasx_xvadd_w(t1, t3); + temp1 = __lasx_xvsub_w(t2, t4); + temp2 = __lasx_xvadd_w(t2, t4); + temp3 = __lasx_xvsub_w(t1, t3); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 3, temp1, 3, temp2, 3, temp3, 3, + temp0, temp1, temp2, temp3); + + /* second loops */ + t1 = __lasx_xvpickev_w(temp1, temp0); + t2 = __lasx_xvpickev_w(temp3, temp2); + t1 = __lasx_xvpickev_h(t2, t1); + t3 = __lasx_xvpickod_w(temp1, temp0); + t4 = __lasx_xvpickod_w(temp3, temp2); + temp1 = __lasx_xvpickev_h(t4, t3); + temp2 = __lasx_xvpermi_q(t1, t1, 0x00); + temp3 = __lasx_xvpermi_q(t1, t1, 0x11); + t1 = __lasx_xvdp2add_w_h(const_6, temp2, const_7); + t2 = __lasx_xvdp2_w_h(temp3, const_8); + t3 = __lasx_xvadd_w(t1, t2); + t4 = __lasx_xvsub_w(t1, t2); + t4 = __lasx_xvpermi_d(t4, 0x4E); + + DUP4_ARG2(__lasx_xvdp2_w_h, temp1, const_9, temp1, const_10, temp1, + const_11, temp1, const_12, t1, t2, temp2, temp3); + + temp0 = __lasx_xvpermi_q(t2, t1, 0x20); + temp1 = __lasx_xvpermi_q(t2, t1, 0x31); + t1 = __lasx_xvadd_w(temp0, temp1); + temp0 = __lasx_xvpermi_q(temp3, temp2, 0x20); + temp1 = __lasx_xvpermi_q(temp3, temp2, 0x31); + t2 = __lasx_xvadd_w(temp1, temp0); + temp0 = __lasx_xvadd_w(t1, t3); + temp1 = __lasx_xvadd_w(t2, t4); + temp2 = __lasx_xvsub_w(t4, t2); + temp3 = __lasx_xvsub_w(t3, t1); + temp2 = __lasx_xvaddi_wu(temp2, 1); + temp3 = __lasx_xvaddi_wu(temp3, 1); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 7, temp1, 7, temp2, 7, temp3, 7, + temp0, temp1, temp2, temp3); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dest + stride, 0, dest + stride2, 0, + dest + stride3, 0, const_1, const_2, const_3, const_4); + DUP4_ARG2(__lasx_xvldrepl_w, dst, 0, dst + stride, 0, dst + stride2, 0, + dst + stride3, 0, const_5, const_6, const_7, const_8); + + DUP4_ARG2(__lasx_xvilvl_w, const_2, const_1, const_4, const_3, const_5, + const_6, const_7, const_8, const_1, const_2, const_3, const_4); + DUP4_ARG1(__lasx_vext2xv_wu_bu, const_1, const_2, const_3, const_4, + const_1, const_2, const_3, const_4); + DUP4_ARG2(__lasx_xvadd_w, temp0, const_1, temp1, const_2, temp2, const_3, + temp3, const_4, temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_xvclip255_w, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvpickev_h, temp1, temp0, temp3, temp2, temp0, temp1); + temp0 = __lasx_xvpickev_b(temp1, temp0); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dest + stride, 0, 4); + __lasx_xvstelm_w(temp0, dest + stride2, 0, 1); + __lasx_xvstelm_w(temp0, dest + stride3, 0, 5); + __lasx_xvstelm_w(temp0, dst, 0, 6); + __lasx_xvstelm_w(temp0, dst + stride, 0, 2); + __lasx_xvstelm_w(temp0, dst + stride2, 0, 7); + __lasx_xvstelm_w(temp0, dst + stride3, 0, 3); +} + +void ff_vc1_inv_trans_4x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + uint8_t *dst1 = dest + stride; + uint8_t *dst2 = dst1 + stride; + uint8_t *dst3 = dst2 + stride; + __m256i in0, in1, in2, in3, temp0, temp1, const_dc; + __m256i zero = {0}; + + dc = (17 * dc + 4) >> 3; + dc = (17 * dc + 64) >> 7; + const_dc = __lasx_xvreplgr2vr_h(dc); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dst1, 0, dst2, 0, dst3, 0, + in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_w, in1, in0, in3, in2, temp0, temp1); + in0 = __lasx_xvpermi_q(temp1, temp0, 0x20); + temp0 = __lasx_xvilvl_b(zero, in0); + in0 = __lasx_xvadd_h(temp0, const_dc); + temp0 = __lasx_xvssrarni_bu_h(in0, in0, 0); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dst1, 0, 1); + __lasx_xvstelm_w(temp0, dst2, 0, 4); + __lasx_xvstelm_w(temp0, dst3, 0, 5); +} + +void ff_vc1_inv_trans_4x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block) +{ + uint8_t *dst1 = dest + stride; + uint8_t *dst2 = dst1 + stride; + uint8_t *dst3 = dst2 + stride; + __m256i in0, in1, in2, in3; + __m256i temp0, temp1, temp2, temp3, t1, t2; + + __m256i const_1 = {0x0011001100110011, 0xFFEF0011FFEF0011, + 0x0011001100110011, 0xFFEF0011FFEF0011}; + __m256i const_2 = {0x000A0016000A0016, 0x0016FFF60016FFF6, + 0x000A0016000A0016, 0x0016FFF60016FFF6}; + __m256i const_64 = {0x0000004000000040, 0x0000004000000040, + 0x0000004000000040, 0x0000004000000040}; + + DUP2_ARG2(__lasx_xvld, block, 0, block, 32, in0, in1); + /* first loops */ + temp0 = __lasx_xvilvl_d(in1, in0); + temp1 = __lasx_xvpickev_h(temp0, temp0); + temp2 = __lasx_xvpickod_h(temp0, temp0); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_1, temp2, const_2, t1, t2); + t1 = __lasx_xvaddi_wu(t1, 4); + in0 = __lasx_xvadd_w(t1, t2); + in1 = __lasx_xvsub_w(t1, t2); + DUP2_ARG2(__lasx_xvsrai_w, in0, 3, in1, 3, in0, in1); + /* second loops */ + temp0 = __lasx_xvpickev_h(in1, in0); + temp1 = __lasx_xvpermi_q(temp0, temp0, 0x00); + temp2 = __lasx_xvpermi_q(temp0, temp0, 0x11); + const_1 = __lasx_xvpermi_d(const_1, 0xD8); + const_2 = __lasx_xvpermi_d(const_2, 0xD8); + t1 = __lasx_xvdp2add_w_h(const_64, temp1, const_1); + t2 = __lasx_xvdp2_w_h(temp2, const_2); + in0 = __lasx_xvadd_w(t1, t2); + in1 = __lasx_xvsub_w(t1, t2); + DUP2_ARG2(__lasx_xvsrai_w, in0, 7, in1, 7, in0, in1); + temp0 = __lasx_xvshuf4i_w(in0, 0x9C); + temp1 = __lasx_xvshuf4i_w(in1, 0x9C); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dst1, 0, dst2, 0, dst3, 0, + in0, in1, in2, in3); + temp2 = __lasx_xvilvl_w(in2, in0); + temp2 = __lasx_vext2xv_wu_bu(temp2); + temp3 = __lasx_xvilvl_w(in1, in3); + temp3 = __lasx_vext2xv_wu_bu(temp3); + temp0 = __lasx_xvadd_w(temp0, temp2); + temp1 = __lasx_xvadd_w(temp1, temp3); + DUP2_ARG1(__lasx_xvclip255_w, temp0, temp1, temp0, temp1); + temp1 = __lasx_xvpickev_h(temp1, temp0); + temp0 = __lasx_xvpickev_b(temp1, temp1); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dst1, 0, 5); + __lasx_xvstelm_w(temp0, dst2, 0, 4); + __lasx_xvstelm_w(temp0, dst3, 0, 1); +} + +static void put_vc1_mspel_mc_h_v_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int hmode, int vmode, + int rnd) +{ + __m256i in0, in1, in2, in3; + __m256i t0, t1, t2, t3, t4, t5, t6, t7; + __m256i temp0, temp1, const_para1_2, const_para0_3; + __m256i const_r, const_sh; + __m256i sh = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + static const uint8_t para_value[][4] = {{4, 3, 53, 18}, + {1, 1, 9, 9}, + {3, 4, 18, 53}}; + static const int shift_value[] = {0, 5, 1, 5}; + int shift = (shift_value[hmode] + shift_value[vmode]) >> 1; + int r = (1 << (shift - 1)) + rnd - 1; + const uint8_t *para_v = para_value[vmode - 1]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride4 = stride << 2; + ptrdiff_t stride3 = stride2 + stride; + + const_r = __lasx_xvreplgr2vr_h(r); + const_sh = __lasx_xvreplgr2vr_h(shift); + src -= 1, src -= stride; + const_para0_3 = __lasx_xvldrepl_h(para_v, 0); + const_para1_2 = __lasx_xvldrepl_h(para_v, 2); + DUP4_ARG2(__lasx_xvld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, temp0, temp1); + t0 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t0 = __lasx_xvdp2sub_h_bu(t0, temp1, const_para0_3); + src += stride4; + in0 = __lasx_xvld(src, 0); + in0 = __lasx_xvpermi_d(in0, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in3, in2, in0, in1, temp0, temp1); + t1 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t1 = __lasx_xvdp2sub_h_bu(t1, temp1, const_para0_3); + src += stride; + in1 = __lasx_xvld(src, 0); + in1 = __lasx_xvpermi_d(in1, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in0, in3, in1, in2, temp0, temp1); + t2 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t2 = __lasx_xvdp2sub_h_bu(t2, temp1, const_para0_3); + src += stride; + in2 = __lasx_xvld(src, 0); + in2 = __lasx_xvpermi_d(in2, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in1, in0, in2, in3, temp0, temp1); + t3 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t3 = __lasx_xvdp2sub_h_bu(t3, temp1, const_para0_3); + src += stride; + in3 = __lasx_xvld(src, 0); + in3 = __lasx_xvpermi_d(in3, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, temp0, temp1); + t4 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t4 = __lasx_xvdp2sub_h_bu(t4, temp1, const_para0_3); + src += stride; + in0 = __lasx_xvld(src, 0); + in0 = __lasx_xvpermi_d(in0, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in3, in2, in0, in1, temp0, temp1); + t5 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t5 = __lasx_xvdp2sub_h_bu(t5, temp1, const_para0_3); + src += stride; + in1 = __lasx_xvld(src, 0); + in1 = __lasx_xvpermi_d(in1, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in0, in3, in1, in2, temp0, temp1); + t6 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t6 = __lasx_xvdp2sub_h_bu(t6, temp1, const_para0_3); + src += stride; + in2 = __lasx_xvld(src, 0); + in2 = __lasx_xvpermi_d(in2, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in1, in0, in2, in3, temp0, temp1); + t7 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t7 = __lasx_xvdp2sub_h_bu(t7, temp1, const_para0_3); + DUP4_ARG2(__lasx_xvadd_h, t0, const_r, t1, const_r, t2, const_r, t3, + const_r, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvadd_h, t4, const_r, t5, const_r, t6, const_r, t7, + const_r, t4, t5, t6, t7); + DUP4_ARG2(__lasx_xvsra_h, t0, const_sh, t1, const_sh, t2, const_sh, + t3, const_sh, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvsra_h, t4, const_sh, t5, const_sh, t6, const_sh, + t7, const_sh, t4, t5, t6, t7); + LASX_TRANSPOSE8x8_H(t0, t1, t2, t3, t4, t5, t6, t7, t0, + t1, t2, t3, t4, t5, t6, t7); + para_v = para_value[hmode - 1]; + const_para0_3 = __lasx_xvldrepl_h(para_v, 0); + const_para1_2 = __lasx_xvldrepl_h(para_v, 2); + const_para0_3 = __lasx_vext2xv_h_b(const_para0_3); + const_para1_2 = __lasx_vext2xv_h_b(const_para1_2); + r = 64 - rnd; + const_r = __lasx_xvreplgr2vr_w(r); + DUP4_ARG2(__lasx_xvpermi_d, t0, 0x72, t1, 0x72, t2, 0x72, t0, 0xD8, + in0, in1, in2, t0); + DUP4_ARG2(__lasx_xvpermi_d, t1, 0xD8, t2, 0xD8, t3, 0xD8, t4, 0xD8, + t1, t2, t3, t4); + DUP2_ARG2(__lasx_xvpermi_d, t5, 0xD8, t6, 0xD8, t5, t6); + t7 = __lasx_xvpermi_d(t7, 0xD8); + DUP2_ARG2(__lasx_xvilvl_h, t2, t1, t3, t0, temp0, temp1); + t0 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t0 = __lasx_xvdp2sub_w_h(t0, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t3, t2, t4, t1, temp0, temp1); + t1 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t1 = __lasx_xvdp2sub_w_h(t1, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t4, t3, t5, t2, temp0, temp1); + t2 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t2 = __lasx_xvdp2sub_w_h(t2, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t5, t4, t6, t3, temp0, temp1); + t3 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t3 = __lasx_xvdp2sub_w_h(t3, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t6, t5, t7, t4, temp0, temp1); + t4 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t4 = __lasx_xvdp2sub_w_h(t4, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t7, t6, in0, t5, temp0, temp1); + t5 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t5 = __lasx_xvdp2sub_w_h(t5, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, in0, t7, in1, t6, temp0, temp1); + t6 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t6 = __lasx_xvdp2sub_w_h(t6, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, in1, in0, in2, t7, temp0, temp1); + t7 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t7 = __lasx_xvdp2sub_w_h(t7, temp1, const_para0_3); + DUP4_ARG2(__lasx_xvadd_w, t0, const_r, t1, const_r, t2, const_r, + t3, const_r, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvadd_w, t4, const_r, t5, const_r, t6, const_r, + t7, const_r, t4, t5, t6, t7); + DUP4_ARG2(__lasx_xvsrai_w, t0, 7, t1, 7, t2, 7, t3, 7, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvsrai_w, t4, 7, t5, 7, t6, 7, t7, 7, t4, t5, t6, t7); + LASX_TRANSPOSE8x8_W(t0, t1, t2, t3, t4, t5, t6, t7, + t0, t1, t2, t3, t4, t5, t6, t7); + DUP4_ARG1(__lasx_xvclip255_w, t0, t1, t2, t3, t0, t1, t2, t3); + DUP4_ARG1(__lasx_xvclip255_w, t4, t5, t6, t7, t4, t5, t6, t7); + DUP4_ARG2(__lasx_xvpickev_h, t1, t0, t3, t2, t5, t4, t7, t6, + t0, t1, t2, t3); + DUP2_ARG2(__lasx_xvpickev_b, t1, t0, t3, t2, t0, t1); + t0 = __lasx_xvperm_w(t0, sh); + t1 = __lasx_xvperm_w(t1, sh); + __lasx_xvstelm_d(t0, dst, 0, 0); + __lasx_xvstelm_d(t0, dst + stride, 0, 1); + __lasx_xvstelm_d(t0, dst + stride2, 0, 2); + __lasx_xvstelm_d(t0, dst + stride3, 0, 3); + dst += stride4; + __lasx_xvstelm_d(t1, dst, 0, 0); + __lasx_xvstelm_d(t1, dst + stride, 0, 1); + __lasx_xvstelm_d(t1, dst + stride2, 0, 2); + __lasx_xvstelm_d(t1, dst + stride3, 0, 3); +} + +#define PUT_VC1_MSPEL_MC_LASX(hmode, vmode) \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_v_lasx(dst, src, stride, hmode, vmode, rnd); \ +} \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_v_lasx(dst, src, stride, hmode, vmode, rnd); \ + put_vc1_mspel_mc_h_v_lasx(dst + 8, src + 8, stride, hmode, vmode, rnd); \ + dst += 8 * stride, src += 8 * stride; \ + put_vc1_mspel_mc_h_v_lasx(dst, src, stride, hmode, vmode, rnd); \ + put_vc1_mspel_mc_h_v_lasx(dst + 8, src + 8, stride, hmode, vmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_LASX(1, 1); +PUT_VC1_MSPEL_MC_LASX(1, 2); +PUT_VC1_MSPEL_MC_LASX(1, 3); + +PUT_VC1_MSPEL_MC_LASX(2, 1); +PUT_VC1_MSPEL_MC_LASX(2, 2); +PUT_VC1_MSPEL_MC_LASX(2, 3); + +PUT_VC1_MSPEL_MC_LASX(3, 1); +PUT_VC1_MSPEL_MC_LASX(3, 2); +PUT_VC1_MSPEL_MC_LASX(3, 3); + +void ff_put_no_rnd_vc1_chroma_mc8_lasx(uint8_t *dst /* align 8 */, + uint8_t *src /* align 1 */, + ptrdiff_t stride, int h, int x, int y) +{ + const int intA = (8 - x) * (8 - y); + const int intB = (x) * (8 - y); + const int intC = (8 - x) * (y); + const int intD = (x) * (y); + __m256i src00, src01, src10, src11; + __m256i A, B, C, D; + int i; + + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + A = __lasx_xvreplgr2vr_h(intA); + B = __lasx_xvreplgr2vr_h(intB); + C = __lasx_xvreplgr2vr_h(intC); + D = __lasx_xvreplgr2vr_h(intD); + for(i = 0; i < h; i++){ + DUP2_ARG2(__lasx_xvld, src, 0, src, 1, src00, src01); + src += stride; + DUP2_ARG2(__lasx_xvld, src, 0, src, 1, src10, src11); + + DUP4_ARG1(__lasx_vext2xv_hu_bu, src00, src01, src10, src11, + src00, src01, src10, src11); + DUP4_ARG2(__lasx_xvmul_h, src00, A, src01, B, src10, C, src11, D, + src00, src01, src10, src11); + src00 = __lasx_xvadd_h(src00, src01); + src10 = __lasx_xvadd_h(src10, src11); + src00 = __lasx_xvadd_h(src00, src10); + src00 = __lasx_xvaddi_hu(src00, 28); + src00 = __lasx_xvsrli_h(src00, 6); + src00 = __lasx_xvpickev_b(src00, src00); + __lasx_xvstelm_d(src00, dst, 0, 0); + dst += stride; + } +} + +static void put_vc1_mspel_mc_v_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int vmode, int rnd) +{ + __m256i in0, in1, in2, in3, temp0, temp1, t0; + __m256i const_para0_3, const_para1_2, const_r, const_sh; + static const uint16_t para_value[][2] = {{0x0304, 0x1235}, + {0x0101, 0x0909}, + {0x0403, 0x3512}}; + const uint16_t *para_v = para_value[vmode - 1]; + static const int shift_value[] = {0, 6, 4, 6}; + static int add_value[3]; + ptrdiff_t stride_2x = stride << 1; + int i = 0; + add_value[2] = add_value[0] = 31 + rnd, add_value[1] = 7 + rnd; + + const_r = __lasx_xvreplgr2vr_h(add_value[vmode - 1]); + const_sh = __lasx_xvreplgr2vr_h(shift_value[vmode]); + const_para0_3 = __lasx_xvreplgr2vr_h(*para_v); + const_para1_2 = __lasx_xvreplgr2vr_h(*(para_v + 1)); + + DUP2_ARG2(__lasx_xvld, src - stride, 0, src, 0, in0, in1); + in2 = __lasx_xvld(src + stride, 0); + in0 = __lasx_xvpermi_d(in0, 0xD8); + in1 = __lasx_xvpermi_d(in1, 0xD8); + in2 = __lasx_xvpermi_d(in2, 0xD8); + for (; i < 16; i++) { + in3 = __lasx_xvld(src + stride_2x, 0); + in3 = __lasx_xvpermi_d(in3, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, temp0, temp1); + t0 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t0 = __lasx_xvdp2sub_h_bu(t0, temp1, const_para0_3); + t0 = __lasx_xvadd_h(t0, const_r); + t0 = __lasx_xvsra_h(t0, const_sh); + t0 = __lasx_xvclip255_h(t0); + t0 = __lasx_xvpickev_b(t0, t0); + __lasx_xvstelm_d(t0, dst, 0, 0); + __lasx_xvstelm_d(t0, dst, 8, 2); + dst += stride; + src += stride; + in0 = in1; + in1 = in2; + in2 = in3; + } +} + +#define PUT_VC1_MSPEL_MC_V_LASX(vmode) \ +void ff_put_vc1_mspel_mc0 ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_v_lasx(dst, src, stride, vmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_V_LASX(1); +PUT_VC1_MSPEL_MC_V_LASX(2); +PUT_VC1_MSPEL_MC_V_LASX(3); + +#define ROW_LASX(in0, in1, in2, in3, out0) \ + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, tmp0_m, tmp1_m); \ + out0 = __lasx_xvdp2_h_bu(tmp0_m, const_para1_2); \ + out0 = __lasx_xvdp2sub_h_bu(out0, tmp1_m, const_para0_3); \ + out0 = __lasx_xvadd_h(out0, const_r); \ + out0 = __lasx_xvsra_h(out0, const_sh); \ + out0 = __lasx_xvclip255_h(out0); \ + out0 = __lasx_xvpickev_b(out0, out0); \ + out0 = __lasx_xvpermi_d(out0, 0xd8); \ + +static void put_vc1_mspel_mc_h_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int hmode, int rnd) +{ + __m256i in0, in1, in2, in3, in4, in5, in6, in7, + in8, in9, in10, in11, in12, in13, in14, in15; + __m256i out0, out1, out2, out3, out4, out5, out6, out7, out8, out9, + out10, out11, out12, out13, out14, out15, out16, out17, out18; + __m256i const_para0_3, const_para1_2, const_r, const_sh; + __m256i tmp0_m, tmp1_m, tmp2_m, tmp3_m; + __m256i tmp4_m, tmp5_m, tmp6_m, tmp7_m; + __m256i t0, t1, t2, t3, t4, t5, t6, t7; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride4 = stride << 2; + ptrdiff_t stride3 = stride2 + stride; + static const uint16_t para_value[][2] = {{0x0304, 0x1235}, + {0x0101, 0x0909}, + {0x0403, 0x3512}}; + const uint16_t *para_v = para_value[hmode - 1]; + static const int shift_value[] = {0, 6, 4, 6}; + static int add_value[3]; + uint8_t *_src = (uint8_t*)src - 1; + add_value[2] = add_value[0] = 32 - rnd, add_value[1] = 8 - rnd; + + const_r = __lasx_xvreplgr2vr_h(add_value[hmode - 1]); + const_sh = __lasx_xvreplgr2vr_h(shift_value[hmode]); + const_para0_3 = __lasx_xvreplgr2vr_h(*para_v); + const_para1_2 = __lasx_xvreplgr2vr_h(*(para_v + 1)); + + in0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in1, in2); + in3 = __lasx_xvldx(_src, stride3); + _src += stride4; + in4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in5, in6); + in7 = __lasx_xvldx(_src, stride3); + _src += stride4; + in8 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in9, in10); + in11 = __lasx_xvldx(_src, stride3); + _src += stride4; + in12 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in13, in14); + in15 = __lasx_xvldx(_src, stride3); + DUP4_ARG2(__lasx_xvilvl_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvl_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out0, out2, out4, out6); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out1, out3, out5, out7); + + DUP4_ARG2(__lasx_xvilvh_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvh_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out8, out10, out12, out14); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out9, out11, out13, out15); + DUP2_ARG3(__lasx_xvpermi_q, out0, out0, 0x31, out1, out1, 0x31, out16, out17); + out18 = __lasx_xvpermi_q(out2, out2, 0x31); + + DUP4_ARG2(__lasx_xvpermi_d, out0, 0xD8, out1, 0xD8, out2, 0xD8, out3, 0xD8, + out0, out1, out2, out3); + DUP4_ARG2(__lasx_xvpermi_d, out4, 0xD8, out5, 0xD8, out6, 0xD8, out7, 0xD8, + out4, out5, out6, out7); + DUP4_ARG2(__lasx_xvpermi_d, out8, 0xD8, out9, 0xD8, out10, 0xD8, out11, + 0xD8, out8, out9, out10, out11); + DUP4_ARG2(__lasx_xvpermi_d, out12, 0xD8, out13, 0xD8, out14, 0xD8, out15, + 0xD8, out12, out13, out14, out15); + out16 = __lasx_xvpermi_d(out16, 0xD8); + out17 = __lasx_xvpermi_d(out17, 0xD8); + out18 = __lasx_xvpermi_d(out18, 0xD8); + + ROW_LASX(out0, out1, out2, out3, in0); + ROW_LASX(out1, out2, out3, out4, in1); + ROW_LASX(out2, out3, out4, out5, in2); + ROW_LASX(out3, out4, out5, out6, in3); + ROW_LASX(out4, out5, out6, out7, in4); + ROW_LASX(out5, out6, out7, out8, in5); + ROW_LASX(out6, out7, out8, out9, in6); + ROW_LASX(out7, out8, out9, out10, in7); + ROW_LASX(out8, out9, out10, out11, in8); + ROW_LASX(out9, out10, out11, out12, in9); + ROW_LASX(out10, out11, out12, out13, in10); + ROW_LASX(out11, out12, out13, out14, in11); + ROW_LASX(out12, out13, out14, out15, in12); + ROW_LASX(out13, out14, out15, out16, in13); + ROW_LASX(out14, out15, out16, out17, in14); + ROW_LASX(out15, out16, out17, out18, in15); + + DUP4_ARG2(__lasx_xvilvl_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvl_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out0, out2, out4, out6); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out1, out3, out5, out7); + + DUP4_ARG2(__lasx_xvilvh_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvh_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out8, out10, out12, out14); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out9, out11, out13, out15); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out2, dst, 0, 0); + __lasx_xvstelm_d(out2, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out3, dst, 0, 0); + __lasx_xvstelm_d(out3, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out4, dst, 0, 0); + __lasx_xvstelm_d(out4, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out5, dst, 0, 0); + __lasx_xvstelm_d(out5, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out6, dst, 0, 0); + __lasx_xvstelm_d(out6, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out7, dst, 0, 0); + __lasx_xvstelm_d(out7, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out8, dst, 0, 0); + __lasx_xvstelm_d(out8, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out9, dst, 0, 0); + __lasx_xvstelm_d(out9, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out10, dst, 0, 0); + __lasx_xvstelm_d(out10, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out11, dst, 0, 0); + __lasx_xvstelm_d(out11, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out12, dst, 0, 0); + __lasx_xvstelm_d(out12, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out13, dst, 0, 0); + __lasx_xvstelm_d(out13, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out14, dst, 0, 0); + __lasx_xvstelm_d(out14, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out15, dst, 0, 0); + __lasx_xvstelm_d(out15, dst, 8, 1); +} + +#define PUT_VC1_MSPEL_MC_H_LASX(hmode) \ +void ff_put_vc1_mspel_mc ## hmode ## 0_16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_lasx(dst, src, stride, hmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_H_LASX(1); +PUT_VC1_MSPEL_MC_H_LASX(2); +PUT_VC1_MSPEL_MC_H_LASX(3); diff --git a/libavcodec/loongarch/vc1dsp_loongarch.h b/libavcodec/loongarch/vc1dsp_loongarch.h new file mode 100644 index 0000000000..398631aecc --- /dev/null +++ b/libavcodec/loongarch/vc1dsp_loongarch.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_VC1DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_VC1DSP_LOONGARCH_H + +#include "libavcodec/vc1dsp.h" +#include "libavutil/avassert.h" + +void ff_vc1_inv_trans_8x8_lasx(int16_t block[64]); +void ff_vc1_inv_trans_8x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_8x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_8x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x8_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *blokc); +void ff_vc1_inv_trans_4x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); + +#define FF_PUT_VC1_MSPEL_MC_LASX(hmode, vmode) \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_LASX(1, 1); +FF_PUT_VC1_MSPEL_MC_LASX(1, 2); +FF_PUT_VC1_MSPEL_MC_LASX(1, 3); + +FF_PUT_VC1_MSPEL_MC_LASX(2, 1); +FF_PUT_VC1_MSPEL_MC_LASX(2, 2); +FF_PUT_VC1_MSPEL_MC_LASX(2, 3); + +FF_PUT_VC1_MSPEL_MC_LASX(3, 1); +FF_PUT_VC1_MSPEL_MC_LASX(3, 2); +FF_PUT_VC1_MSPEL_MC_LASX(3, 3); + +#define FF_PUT_VC1_MSPEL_MC_V_LASX(vmode) \ +void ff_put_vc1_mspel_mc0 ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_V_LASX(1); +FF_PUT_VC1_MSPEL_MC_V_LASX(2); +FF_PUT_VC1_MSPEL_MC_V_LASX(3); + +#define FF_PUT_VC1_MSPEL_MC_H_LASX(hmode) \ +void ff_put_vc1_mspel_mc ## hmode ## 0_16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_H_LASX(1); +FF_PUT_VC1_MSPEL_MC_H_LASX(2); +FF_PUT_VC1_MSPEL_MC_H_LASX(3); + +void ff_put_no_rnd_vc1_chroma_mc8_lasx(uint8_t *dst /* align 8 */, + uint8_t *src /* align 1 */, + ptrdiff_t stride, int h, int x, int y); + +#endif /* AVCODEC_LOONGARCH_VC1DSP_LOONGARCH_H */ diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c index c25a6f3adf..04fc8b12f3 100644 --- a/libavcodec/vc1dsp.c +++ b/libavcodec/vc1dsp.c @@ -1039,4 +1039,6 @@ av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) ff_vc1dsp_init_x86(dsp); if (ARCH_MIPS) ff_vc1dsp_init_mips(dsp); + if (ARCH_LOONGARCH) + ff_vc1dsp_init_loongarch(dsp); } diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h index 75db62b1b4..c6443acb20 100644 --- a/libavcodec/vc1dsp.h +++ b/libavcodec/vc1dsp.h @@ -88,5 +88,6 @@ void ff_vc1dsp_init_arm(VC1DSPContext* dsp); void ff_vc1dsp_init_ppc(VC1DSPContext *c); void ff_vc1dsp_init_x86(VC1DSPContext* dsp); void ff_vc1dsp_init_mips(VC1DSPContext* dsp); +void ff_vc1dsp_init_loongarch(VC1DSPContext* dsp); #endif /* AVCODEC_VC1DSP_H */ From d8ea7a67ba62f5d4520e75e56b9954d80e7ff223 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Dec 2021 22:26:00 +0100 Subject: [PATCH 612/894] avcodec/vqavideo: reset accounting on error Fixes: Timeout (same growing chunk is decoded to failure repeatedly) Fixes: 42582/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VQA_fuzzer-6531195591065600 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vqavideo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 7c1d42bcac..1d97855e60 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -608,13 +608,14 @@ static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame) if (s->partial_countdown <= 0) { bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index); /* decompress codebook */ - if ((res = decode_format80(s, s->next_codebook_buffer_index, - s->codebook, s->codebook_size, 0)) < 0) - return res; + res = decode_format80(s, s->next_codebook_buffer_index, + s->codebook, s->codebook_size, 0); /* reset accounting */ s->next_codebook_buffer_index = 0; s->partial_countdown = s->partial_count; + if (res < 0) + return res; } } From d6c16f42ccebca917bb9861c619abcf71ab25762 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 17 Dec 2021 20:43:15 +0100 Subject: [PATCH 613/894] avcodec/tiff: Pass max_pixels to mjpeg context Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 870e0666aa..9af602eef7 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -2155,6 +2155,7 @@ static av_cold int tiff_init(AVCodecContext *avctx) s->avctx_mjpeg->flags2 = avctx->flags2; s->avctx_mjpeg->dct_algo = avctx->dct_algo; s->avctx_mjpeg->idct_algo = avctx->idct_algo; + s->avctx_mjpeg->max_pixels = avctx->max_pixels; ret = avcodec_open2(s->avctx_mjpeg, codec, NULL); if (ret < 0) { return ret; From cfa1f0e214d07f0fdc027f2ec760eb9fd3fac85e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 17 Dec 2021 20:52:32 +0100 Subject: [PATCH 614/894] avcodec/tiff: Use ff_set_dimensions() for setting up mjpeg context dimensions sets coded_width / coded_height too to keep them consistent with width / height Fixes: OOM Fixes: 42263/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-5653333619113984 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 9af602eef7..60773d59ed 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -724,13 +724,14 @@ static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame, static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) { TiffContext *s = avctx->priv_data; + int ret = ff_set_dimensions(s->avctx_mjpeg, s->width, s->height); + + if (ret < 0) + return ret; s->jpgframe->width = s->width; s->jpgframe->height = s->height; - s->avctx_mjpeg->width = s->width; - s->avctx_mjpeg->height = s->height; - return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); } @@ -971,14 +972,14 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; - int ret; + int ret = ff_set_dimensions(s->avctx_mjpeg, s->tile_width, s->tile_length); + + if (ret < 0) + return ret; s->jpgframe->width = s->tile_width; s->jpgframe->height = s->tile_length; - s->avctx_mjpeg->width = s->tile_width; - s->avctx_mjpeg->height = s->tile_length; - has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); From b8a4b273bea57c4004f2c90fd8a7618f3757eece Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 18 Dec 2021 21:15:33 +0100 Subject: [PATCH 615/894] avcodec/mjpegdec: Fix exif rotation->displaymatrix conversion The cases in which there was flipping together with a rotation that is not a multiple of the identity were wrong. Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 8b154ce0ab..0dbbc14bae 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -2896,14 +2896,14 @@ the_end: break; case 5: av_display_rotation_set(matrix, 90.0); - av_display_matrix_flip(matrix, 0, 1); + av_display_matrix_flip(matrix, 1, 0); break; case 6: av_display_rotation_set(matrix, 90.0); break; case 7: av_display_rotation_set(matrix, -90.0); - av_display_matrix_flip(matrix, 0, 1); + av_display_matrix_flip(matrix, 1, 0); break; case 8: av_display_rotation_set(matrix, -90.0); From 4e21fff19d1df0ce75d0a19e44865be152197418 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 18 Dec 2021 21:40:26 +0100 Subject: [PATCH 616/894] fftools/ffmpeg_filter: Fix autorotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of an orthogonal transformation av_display_rotation_get() returns the (anticlockwise) degree that the unit vector in x-direction gets rotated by; get_rotation in cmdutils.c makes a clockwise degree out of this. So if one inserts a transpose filter corresponding to this degree, then the x-vector gets mapped correctly and there are two possibilities for image of the y-vector, namely the two unit vectors orthogonal to the image of the x-vector. E.g. if the x-vector gets rotated by 90° clockwise, then the two possibilities for the y-vector are the unit vector in x direction or its opposite. The latter case is a simple 90° rotation for both vectors* whereas the former is a simple 90° clockwise rotation followed by a horizontal flip. These two cases can be distinguished by looking at the x-coordinate of the image of the y-vector, i.e. by looking at displaymatrix[3]. Similarly for the case of a 270° clockwise rotation. These two cases were previously wrong (they were made to match wrongly parsed exif rotation tag values). *: For display matrices, the y-axis points downward. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 501a0acd61..8c929ab9fa 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -761,12 +761,12 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, theta = get_rotation(displaymatrix); if (fabs(theta - 90) < 1.0) { + ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock"); if (displaymatrix[3] > 0) { ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); if (ret < 0) return ret; } - ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock"); } else if (fabs(theta - 180) < 1.0) { if (displaymatrix[0] < 0) { ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); @@ -777,12 +777,12 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); } } else if (fabs(theta - 270) < 1.0) { + ret = insert_filter(&last_filter, &pad_idx, "transpose", "cclock"); if (displaymatrix[3] < 0) { ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); if (ret < 0) return ret; } - ret = insert_filter(&last_filter, &pad_idx, "transpose", "cclock"); } else if (fabs(theta) > 1.0) { char rotate_buf[64]; snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta); From 04133eb2d5c794a077125fbbf9b880060f2123a1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 18 Dec 2021 23:19:05 +0100 Subject: [PATCH 617/894] fftools/ffmpeg_filter: Avoid inserting hflip filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The transpose filter has modes equivalent to "rotation by 90°/270°" followed by horizontal flips. Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_filter.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8c929ab9fa..1f6cba2c04 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -761,12 +761,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, theta = get_rotation(displaymatrix); if (fabs(theta - 90) < 1.0) { - ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock"); - if (displaymatrix[3] > 0) { - ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); - if (ret < 0) - return ret; - } + ret = insert_filter(&last_filter, &pad_idx, "transpose", + displaymatrix[3] > 0 ? "cclock_flip" : "clock"); } else if (fabs(theta - 180) < 1.0) { if (displaymatrix[0] < 0) { ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); @@ -777,12 +773,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); } } else if (fabs(theta - 270) < 1.0) { - ret = insert_filter(&last_filter, &pad_idx, "transpose", "cclock"); - if (displaymatrix[3] < 0) { - ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); - if (ret < 0) - return ret; - } + ret = insert_filter(&last_filter, &pad_idx, "transpose", + displaymatrix[3] < 0 ? "clock_flip" : "cclock"); } else if (fabs(theta) > 1.0) { char rotate_buf[64]; snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta); From ab6f9d86a9db7d0743629ecab422cfb61f2a17e1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 18 Dec 2021 23:46:47 +0100 Subject: [PATCH 618/894] avcodec/h2645: Fix SEI->display matrix transformation The earlier code did not account for the fact that av_display_rotation_set() wants the angle in the anticlockwise direction (despite what its documentation stated for a long time); furthermore, the H.2645 spec wants the flips applied first, whereas our code did it the other way around. This can be fixed by negating the angle once for every flip. Signed-off-by: Andreas Rheinhardt --- libavcodec/h264_metadata_bsf.c | 15 ++++++++++++--- libavcodec/h264_slice.c | 9 +++++++++ libavcodec/hevcdec.c | 10 ++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 452a8ec5dc..8c5d19c5a8 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -341,15 +341,24 @@ static int h264_metadata_handle_display_orientation(AVBSFContext *bsf, SEI_TYPE_DISPLAY_ORIENTATION, &message) == 0) { H264RawSEIDisplayOrientation *disp = message->payload; + double angle = disp->anticlockwise_rotation * 180.0 / 65536.0; int32_t *matrix; matrix = av_malloc(9 * sizeof(int32_t)); if (!matrix) return AVERROR(ENOMEM); - av_display_rotation_set(matrix, - disp->anticlockwise_rotation * - 180.0 / 65536.0); + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!disp->hor_flip) * (1 - 2 * !!disp->ver_flip); + + av_display_rotation_set(matrix, angle); av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip); // If there are multiple display orientation messages in an diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 4467882775..c21004df97 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1305,6 +1305,15 @@ static int h264_export_frame_props(H264Context *h) AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (rotation) { + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!o->hflip) * (1 - 2 * !!o->vflip); av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, o->hflip, o->vflip); diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 46d9edf8eb..3aa70e2245 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2769,6 +2769,16 @@ static int set_side_data(HEVCContext *s) if (!rotation) return AVERROR(ENOMEM); + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!s->sei.display_orientation.hflip) + * (1 - 2 * !!s->sei.display_orientation.vflip); av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, s->sei.display_orientation.hflip, From bb813ccb458ea64a68feebcdfa76504fd6969f52 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Fri, 29 Oct 2021 16:41:27 -0400 Subject: [PATCH 619/894] configure: use pkg-config for sndio --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 410f7cb241..23ef2abc9b 100755 --- a/configure +++ b/configure @@ -6821,7 +6821,8 @@ enabled alsa && { check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimesta enabled libjack && require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range -enabled sndio && check_lib sndio sndio.h sio_open -lsndio +enabled sndio && { check_pkg_config sndio sndio "sndio.h" sio_open || + check_lib sndio sndio.h sio_open -lsndio; } if enabled libcdio; then check_pkg_config libcdio libcdio_paranoia "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open || From 7b21841ce45ef4ab486c3c94a714345b878a70fd Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:26 +0100 Subject: [PATCH 620/894] avdevice/dshow: prevent NULL access list_options true would crash when both a video and an audio device were specified as input. Crash would occur on line 784 because ctx->device_unique_name[otherDevType] would be NULL Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index ef78781865..cc0bef0474 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -708,9 +708,9 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum, if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0) return r; ctx->device_filter[devtype] = device_filter; + ctx->device_unique_name[devtype] = device_unique_name; if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0) return r; - av_freep(&device_unique_name); return 0; } @@ -1143,6 +1143,7 @@ static int dshow_read_header(AVFormatContext *avctx) } } } + // don't exit yet, allow it to list crossbar options in dshow_open_device } if (ctx->device_name[VideoDevice]) { if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 || From 7dc33aad45772ca3c0a3092833cf8447d1607663 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:27 +0100 Subject: [PATCH 621/894] avdevice/dshow: implement option to use device video timestamps The dshow avdevice ignores timestamps for video frames provided by the DirectShow device, instead using wallclock time, apparently because the implementer of this code had a device that provided unreliable timestamps. Me (and others) would like to use the device's timestamps. The new use_video_device_timestamps option for dshow device enables them to do so. Since the majority of video devices out there probably provide fine timestamps, this patch sets the default to using the device timestamps, which means best fidelity timestamps are used by default. Using the new option, the user can switch this off and revert to the old behavior, so a fall back remains available in case the device provides broken timestamps. add use_video_device_timestamps to docs. Closes: #8620 Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- doc/indevs.texi | 6 ++++++ libavdevice/dshow.c | 1 + libavdevice/dshow_capture.h | 1 + libavdevice/dshow_pin.c | 11 ++++++----- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 5be647f70a..9d8020311a 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -625,6 +625,12 @@ Save the currently used video capture filter device and its parameters (if the filter supports it) to a file. If a file with the same name exists it will be overwritten. +@item use_video_device_timestamps +If set to @option{false}, the timestamp for video frames will be +derived from the wallclock instead of the timestamp provided by +the capture device. This allows working around devices that +provide unreliable timestamps. + @end table @subsection Examples diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index cc0bef0474..5e6eb9c85d 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1310,6 +1310,7 @@ static const AVOption options[] = { { "audio_device_save", "save audio capture filter device (and properties) to file", OFFSET(audio_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_device_load", "load video capture filter device (and properties) from file", OFFSET(video_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_device_save", "save video capture filter device (and properties) to file", OFFSET(video_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "use_video_device_timestamps", "use device instead of wallclock timestamps for video frames", OFFSET(use_video_device_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC }, { NULL }, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 06ded2ba96..5a2691518c 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -312,6 +312,7 @@ struct dshow_ctx { char *audio_filter_save_file; char *video_filter_load_file; char *video_filter_save_file; + int use_video_device_timestamps; IBaseFilter *device_filter[2]; IPin *device_pin[2]; diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 3dae405e65..8e56dccbfe 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -309,10 +309,14 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) if (!sample) return E_POINTER; + priv_data = pin->filter->priv_data; + s = priv_data; + ctx = s->priv_data; + IMediaSample_GetTime(sample, &orig_curtime, &dummy); orig_curtime += pin->filter->start_time; IReferenceClock_GetTime(clock, &graphtime); - if (devtype == VideoDevice) { + if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ IReferenceClock_GetTime(clock, &curtime); } else { @@ -322,7 +326,7 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) like 437650244077016960 which FFmpeg doesn't like. TODO figure out math. For now just drop them. */ av_log(NULL, AV_LOG_DEBUG, - "dshow dropping initial (or ending) audio frame with odd PTS too high %"PRId64"\n", curtime); + "dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", curtime); return S_OK; } curtime += pin->filter->start_time; @@ -330,9 +334,6 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) buf_size = IMediaSample_GetActualDataLength(sample); IMediaSample_GetPointer(sample, &buf); - priv_data = pin->filter->priv_data; - s = priv_data; - ctx = s->priv_data; index = pin->filter->stream_index; av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d " From 584b0fbe4b6ae4c6a5fadefda0c59889c7238cc7 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:28 +0100 Subject: [PATCH 622/894] avdevice/dshow: query graph and sample time only once No need to query twice, use value we've already unconditionally got. Improve variable names Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow_pin.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 8e56dccbfe..1d0e880480 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -295,9 +295,10 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) uint8_t *buf; int buf_size; /* todo should be a long? */ int index; - int64_t curtime; - int64_t orig_curtime; + int64_t chosentime; + int64_t sampletime; int64_t graphtime; + int use_sample_time = 1; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; IReferenceClock *clock = pin->filter->clock; int64_t dummy; @@ -313,24 +314,27 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) s = priv_data; ctx = s->priv_data; - IMediaSample_GetTime(sample, &orig_curtime, &dummy); - orig_curtime += pin->filter->start_time; + IMediaSample_GetTime(sample, &sampletime, &dummy); IReferenceClock_GetTime(clock, &graphtime); if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ - IReferenceClock_GetTime(clock, &curtime); + chosentime = graphtime; + use_sample_time = 0; } else { - IMediaSample_GetTime(sample, &curtime, &dummy); - if(curtime > 400000000000000000LL) { + if (sampletime > 400000000000000000LL) { /* initial frames sometimes start < 0 (shown as a very large number here, - like 437650244077016960 which FFmpeg doesn't like. + like 437650244077016960 which FFmpeg doesn't like). TODO figure out math. For now just drop them. */ av_log(NULL, AV_LOG_DEBUG, - "dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", curtime); + "dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", sampletime); return S_OK; } - curtime += pin->filter->start_time; + chosentime = sampletime; } + // media sample time is relative to graph start time + sampletime += pin->filter->start_time; + if (use_sample_time) + chosentime += pin->filter->start_time; buf_size = IMediaSample_GetActualDataLength(sample); IMediaSample_GetPointer(sample, &buf); @@ -338,8 +342,8 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d " "timestamp %"PRId64" orig timestamp %"PRId64" graph timestamp %"PRId64" diff %"PRId64" %s\n", - devtypename, buf_size, curtime, orig_curtime, graphtime, graphtime - orig_curtime, ctx->device_name[devtype]); - pin->filter->callback(priv_data, index, buf, buf_size, curtime, devtype); + devtypename, buf_size, chosentime, sampletime, graphtime, graphtime - sampletime, ctx->device_name[devtype]); + pin->filter->callback(priv_data, index, buf, buf_size, chosentime, devtype); return S_OK; } From 271e55987faf41c850dc2c2e719ffb1e097242d9 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:29 +0100 Subject: [PATCH 623/894] avdevice/dshow: handle unknown sample time GetTime may return an error indication that the sample has not timestamps, or may return a NULL start time. In those cases, fall back to graph time. Emit log when that happens. Improve logging in the frame receive function: now logged against correct avclass instead of NULL. Better debug message in case sample dropped: could now be audio or video frame. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow_pin.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 1d0e880480..2d1fa0e882 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -295,14 +295,15 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) uint8_t *buf; int buf_size; /* todo should be a long? */ int index; - int64_t chosentime; - int64_t sampletime; - int64_t graphtime; + int64_t chosentime = 0; + int64_t sampletime = 0; + int64_t graphtime = 0; int use_sample_time = 1; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; IReferenceClock *clock = pin->filter->clock; int64_t dummy; struct dshow_ctx *ctx; + HRESULT hr; dshowdebug("ff_dshow_meminputpin_Receive(%p)\n", this); @@ -314,22 +315,28 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) s = priv_data; ctx = s->priv_data; - IMediaSample_GetTime(sample, &sampletime, &dummy); + hr = IMediaSample_GetTime(sample, &sampletime, &dummy); IReferenceClock_GetTime(clock, &graphtime); if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ chosentime = graphtime; use_sample_time = 0; } else { - if (sampletime > 400000000000000000LL) { + if (hr == VFW_E_SAMPLE_TIME_NOT_SET || sampletime == 0) { + chosentime = graphtime; + use_sample_time = 0; + av_log(s, AV_LOG_DEBUG, + "frame with missing sample timestamp encountered, falling back to graph timestamp\n"); + } + else if (sampletime > 400000000000000000LL) { /* initial frames sometimes start < 0 (shown as a very large number here, like 437650244077016960 which FFmpeg doesn't like). TODO figure out math. For now just drop them. */ - av_log(NULL, AV_LOG_DEBUG, - "dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", sampletime); + av_log(s, AV_LOG_DEBUG, + "dropping initial (or ending) sample with odd PTS too high %"PRId64"\n", sampletime); return S_OK; - } - chosentime = sampletime; + } else + chosentime = sampletime; } // media sample time is relative to graph start time sampletime += pin->filter->start_time; @@ -340,7 +347,7 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) IMediaSample_GetPointer(sample, &buf); index = pin->filter->stream_index; - av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d " + av_log(s, AV_LOG_VERBOSE, "passing through packet of type %s size %8d " "timestamp %"PRId64" orig timestamp %"PRId64" graph timestamp %"PRId64" diff %"PRId64" %s\n", devtypename, buf_size, chosentime, sampletime, graphtime, graphtime - sampletime, ctx->device_name[devtype]); pin->filter->callback(priv_data, index, buf, buf_size, chosentime, devtype); From 937de260eb293000d1bf043974ef56cf9a1ad4e0 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:30 +0100 Subject: [PATCH 624/894] avdevice/dshow: set no-seek flags avdevice/dshow is a realtime device and as such does not support seeking. Therefore, its demuxer format should define the AVFMT_NOBINSEARCH, AVFMT_NOGENSEARCH and AVFMT_NO_BYTE_SEEK flags. With these flags set, attempting to seek (with, e.g., avformat_seek_file()) correctly yields -1 (operation not permitted) instead of -22 (invalid argument). This actually seems to apply to many other devices, at least the gdigrab, v4l2, vfwcap, x11grab, fbdev, kmsgrab and android_camera devices, from reading the source. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 5e6eb9c85d..0ef3b3d13e 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1329,6 +1329,6 @@ const AVInputFormat ff_dshow_demuxer = { .read_header = dshow_read_header, .read_packet = dshow_read_packet, .read_close = dshow_read_close, - .flags = AVFMT_NOFILE, + .flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK, .priv_class = &dshow_class, }; From ec579b4e3609d958a4c7fcec2db85b37243f318f Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:31 +0100 Subject: [PATCH 625/894] avdevice/dshow: implement get_device_list Needed to enable programmatic discovery of DirectShow devices Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 96 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 0ef3b3d13e..e1702c8519 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -202,11 +202,14 @@ fail: * retrieve the device with type specified by devtype and return the * pointer to the object found in *pfilter. * If pfilter is NULL, list all device names. + * If device_list is not NULL, populate it with found devices instead of + * outputting device names to log */ static int dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, - IBaseFilter **pfilter, char **device_unique_name) + IBaseFilter **pfilter, char **device_unique_name, + AVDeviceInfoList **device_list) { struct dshow_ctx *ctx = avctx->priv_data; IBaseFilter *device_filter = NULL; @@ -238,18 +241,19 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, IBindCtx *bind_ctx = NULL; LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; + AVDeviceInfo *device = NULL; int i; r = CoGetMalloc(1, &co_malloc); if (r != S_OK) - goto fail1; + goto fail; r = CreateBindCtx(0, &bind_ctx); if (r != S_OK) - goto fail1; + goto fail; /* GetDisplayname works for both video and audio, DevicePath doesn't */ r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr); if (r != S_OK) - goto fail1; + goto fail; unique_name = dup_wchar_to_utf8(olestr); /* replace ':' with '_' since we use : to delineate between sources */ for (i = 0; i < strlen(unique_name); i++) { @@ -259,34 +263,62 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag); if (r != S_OK) - goto fail1; + goto fail; var.vt = VT_BSTR; r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL); if (r != S_OK) - goto fail1; + goto fail; friendly_name = dup_wchar_to_utf8(var.bstrVal); if (pfilter) { if (strcmp(device_name, friendly_name) && strcmp(device_name, unique_name)) - goto fail1; + goto fail; if (!skip--) { r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name); - goto fail1; + goto fail; } *device_unique_name = unique_name; unique_name = NULL; // success, loop will end now } } else { - av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); - av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); + if (device_list) { + device = av_mallocz(sizeof(AVDeviceInfo)); + if (!device) + goto fail; + + device->device_name = av_strdup(friendly_name); + device->device_description = av_strdup(unique_name); + if (!device->device_name || !device->device_description) + goto fail; + + // make space in device_list for this new device + if (av_reallocp_array(&(*device_list)->devices, + (*device_list)->nb_devices + 1, + sizeof(*(*device_list)->devices)) < 0) + goto fail; + + // store device in list + (*device_list)->devices[(*device_list)->nb_devices] = device; + (*device_list)->nb_devices++; + device = NULL; // copied into array, make sure not freed below + } + else { + av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); + av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); + } } -fail1: +fail: + if (device) { + av_freep(&device->device_name); + av_freep(&device->device_description); + av_free(device); + } if (olestr && co_malloc) IMalloc_Free(co_malloc, olestr); if (bind_ctx) @@ -312,6 +344,39 @@ fail1: return 0; } +static int dshow_get_device_list(AVFormatContext *avctx, AVDeviceInfoList *device_list) +{ + struct dshow_ctx *ctx = avctx->priv_data; + ICreateDevEnum *devenum = NULL; + int r; + int ret = AVERROR(EIO); + + if (!device_list) + return AVERROR(EINVAL); + + CoInitialize(0); + + r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, + &IID_ICreateDevEnum, (void**)&devenum); + if (r != S_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n"); + goto error; + } + + ret = dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL, &device_list); + if (ret < S_OK) + goto error; + ret = dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL, &device_list); + +error: + if (devenum) + ICreateDevEnum_Release(devenum); + + CoUninitialize(); + + return ret; +} + /** * Cycle through available formats using the specified pin, * try to set parameters specified through AVOptions and if successful @@ -705,7 +770,7 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum, char *device_unique_name = NULL; int r; - if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0) + if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name, NULL)) < 0) return r; ctx->device_filter[devtype] = device_filter; ctx->device_unique_name[devtype] = device_unique_name; @@ -765,7 +830,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, av_log(avctx, AV_LOG_INFO, "Capture filter loaded successfully from file \"%s\".\n", filename); } else { - if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name)) < 0) { + if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name, NULL)) < 0) { ret = r; goto error; } @@ -1122,9 +1187,9 @@ static int dshow_read_header(AVFormatContext *avctx) if (ctx->list_devices) { av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n"); - dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL); + dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL, NULL); av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n"); - dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL); + dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL, NULL); ret = AVERROR_EXIT; goto error; } @@ -1329,6 +1394,7 @@ const AVInputFormat ff_dshow_demuxer = { .read_header = dshow_read_header, .read_packet = dshow_read_packet, .read_close = dshow_read_close, + .get_device_list= dshow_get_device_list, .flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK, .priv_class = &dshow_class, }; From 54fdbfc366db8d43eab46c09adc45842c9744fdd Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:32 +0100 Subject: [PATCH 626/894] avdevice/dshow: list_devices: show media type(s) per device the list_devices option of dshow didn't indicate whether a specific device provides audio or video output. This patch iterates through all media formats of all pins exposed by the device to see what types it provides for capture, and prints this to the console for each device. Importantly, this now allows to find devices that provide both audio and video, and devices that provide neither. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 103 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index e1702c8519..8dba04a787 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -197,6 +197,80 @@ fail: return; } +static void +dshow_get_device_media_types(AVFormatContext *avctx, enum dshowDeviceType devtype, + enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, + enum AVMediaType **media_types, int *nb_media_types) +{ + struct dshow_ctx *ctx = avctx->priv_data; + IEnumPins *pins = 0; + IPin *pin; + int has_audio = 0, has_video = 0; + + if (IBaseFilter_EnumPins(device_filter, &pins) != S_OK) + return; + + while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { + IKsPropertySet *p = NULL; + PIN_INFO info = { 0 }; + GUID category; + DWORD r2; + IEnumMediaTypes *types = NULL; + AM_MEDIA_TYPE *type; + + if (IPin_QueryPinInfo(pin, &info) != S_OK) + goto next; + IBaseFilter_Release(info.pFilter); + + if (info.dir != PINDIR_OUTPUT) + goto next; + if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK) + goto next; + if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, + NULL, 0, &category, sizeof(GUID), &r2) != S_OK) + goto next; + if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE)) + goto next; + + if (IPin_EnumMediaTypes(pin, &types) != S_OK) + goto next; + + // enumerate media types exposed by pin + // NB: don't know if a pin can expose both audio and video, check 'm all to be safe + IEnumMediaTypes_Reset(types); + while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { + if (IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) { + has_video = 1; + } else if (IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) { + has_audio = 1; + } + CoTaskMemFree(type); + } + + next: + if (types) + IEnumMediaTypes_Release(types); + if (p) + IKsPropertySet_Release(p); + if (pin) + IPin_Release(pin); + } + + IEnumPins_Release(pins); + + if (has_audio || has_video) { + int nb_types = has_audio + has_video; + *media_types = av_malloc_array(nb_types, sizeof(enum AVMediaType)); + if (*media_types) { + if (has_audio) + (*media_types)[0] = AVMEDIA_TYPE_AUDIO; + if (has_video) + (*media_types)[0 + has_audio] = AVMEDIA_TYPE_VIDEO; + *nb_media_types = nb_types; + } + } +} + /** * Cycle through available devices using the device enumerator devenum, * retrieve the device with type specified by devtype and return the @@ -242,6 +316,8 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; AVDeviceInfo *device = NULL; + enum AVMediaType *media_types = NULL; + int nb_media_types = 0; int i; r = CoGetMalloc(1, &co_malloc); @@ -286,6 +362,12 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, // success, loop will end now } } else { + // get media types exposed by pins of device + if (IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void* ) &device_filter) == S_OK) { + dshow_get_device_media_types(avctx, devtype, sourcetype, device_filter, &media_types, &nb_media_types); + IBaseFilter_Release(device_filter); + device_filter = NULL; + } if (device_list) { device = av_mallocz(sizeof(AVDeviceInfo)); if (!device) @@ -308,12 +390,25 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, device = NULL; // copied into array, make sure not freed below } else { - av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); - av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); + av_log(avctx, AV_LOG_INFO, "\"%s\"", friendly_name); + if (nb_media_types > 0) { + const char* media_type = av_get_media_type_string(media_types[0]); + av_log(avctx, AV_LOG_INFO, " (%s", media_type ? media_type : "unknown"); + for (int i = 1; i < nb_media_types; ++i) { + media_type = av_get_media_type_string(media_types[i]); + av_log(avctx, AV_LOG_INFO, ", %s", media_type ? media_type : "unknown"); + } + av_log(avctx, AV_LOG_INFO, ")"); + } else { + av_log(avctx, AV_LOG_INFO, " (none)"); + } + av_log(avctx, AV_LOG_INFO, "\n"); + av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); } } -fail: + fail: + av_freep(&media_types); if (device) { av_freep(&device->device_name); av_freep(&device->device_description); @@ -1186,9 +1281,7 @@ static int dshow_read_header(AVFormatContext *avctx) } if (ctx->list_devices) { - av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n"); dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL, NULL); - av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n"); dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL, NULL); ret = AVERROR_EXIT; goto error; From a8a530331fba298fa0f8863502906f5d7d17d54f Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:33 +0100 Subject: [PATCH 627/894] avdevice: add info about media types(s) to AVDeviceInfo An avdevice, regardless of whether its category says its an audio or video device, may provide access to devices providing different media types, or even single devices providing multiple media types. Also, some devices may provide no media types. dshow is an example encompassing all of these cases. Users should be provided with this information, so AVDeviceInfo is extended to provide it. Bump avdevice version Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/avdevice.c | 1 + libavdevice/avdevice.h | 2 ++ libavdevice/version.h | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 2ae26ab8e3..8f460c7564 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -157,6 +157,7 @@ void avdevice_free_list_devices(AVDeviceInfoList **device_list) if (dev) { av_freep(&dev->device_name); av_freep(&dev->device_description); + av_freep(&dev->media_types); av_free(dev); } } diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 8370bbc7f2..6f24976dcc 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -457,6 +457,8 @@ void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContex typedef struct AVDeviceInfo { char *device_name; /**< device name, format depends on device */ char *device_description; /**< human friendly name */ + enum AVMediaType *media_types; /**< array indicating what media types(s), if any, a device can provide. If null, cannot provide any */ + int nb_media_types; /**< length of media_types array, 0 if device cannot provide any media types */ } AVDeviceInfo; /** diff --git a/libavdevice/version.h b/libavdevice/version.h index 914e156ec7..41f568d6b0 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 101 +#define LIBAVDEVICE_VERSION_MINOR 1 +#define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ From e4b9aee11c5fff00eb7a491552dca1fe52b1264c Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:34 +0100 Subject: [PATCH 628/894] avdevice/dshow: add media type info to get_device_list The list returned by get_device_list now contains info about what media type(s), if any, can be provided by each device. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 8dba04a787..4b1e942c7a 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -384,6 +384,12 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, sizeof(*(*device_list)->devices)) < 0) goto fail; + // attach media_types to device + device->nb_media_types = nb_media_types; + device->media_types = media_types; + nb_media_types = 0; + media_types = NULL; + // store device in list (*device_list)->devices[(*device_list)->nb_devices] = device; (*device_list)->nb_devices++; @@ -412,6 +418,7 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, if (device) { av_freep(&device->device_name); av_freep(&device->device_description); + // NB: no need to av_freep(&device->media_types), its only moved to device once nothing can fail anymore av_free(device); } if (olestr && co_malloc) From 5c90c13a569fb8c6e11edd1ef9213831f264a8a7 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:35 +0100 Subject: [PATCH 629/894] fftools: provide media type info for devices fftools now print info about what media type(s), if any, are provided by sink and source avdevices. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- fftools/cmdutils.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 882584e9c2..1444ea2f07 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2244,9 +2244,29 @@ double get_rotation(int32_t *displaymatrix) } #if CONFIG_AVDEVICE +static void print_device_list(const AVDeviceInfoList *device_list) +{ + // print devices + for (int i = 0; i < device_list->nb_devices; i++) { + const AVDeviceInfo *device = device_list->devices[i]; + printf("%c %s [%s] (", device_list->default_device == i ? '*' : ' ', + device->device_name, device->device_description); + if (device->nb_media_types > 0) { + for (int j = 0; j < device->nb_media_types; ++j) { + const char* media_type = av_get_media_type_string(device->media_types[j]); + if (j > 0) + printf(", "); + printf("%s", media_type ? media_type : "unknown"); + } + } else { + printf("none"); + } + printf(")\n"); + } +} static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) { - int ret, i; + int ret; AVDeviceInfoList *device_list = NULL; if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) @@ -2258,10 +2278,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) goto fail; } - for (i = 0; i < device_list->nb_devices; i++) { - printf("%c %s [%s]\n", device_list->default_device == i ? '*' : ' ', - device_list->devices[i]->device_name, device_list->devices[i]->device_description); - } + print_device_list(device_list); fail: avdevice_free_list_devices(&device_list); @@ -2270,7 +2287,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) { - int ret, i; + int ret; AVDeviceInfoList *device_list = NULL; if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) @@ -2282,10 +2299,7 @@ static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) goto fail; } - for (i = 0; i < device_list->nb_devices; i++) { - printf("%c %s [%s]\n", device_list->default_device == i ? '*' : ' ', - device_list->devices[i]->device_name, device_list->devices[i]->device_description); - } + print_device_list(device_list); fail: avdevice_free_list_devices(&device_list); From dde92fb7d995a1cf0474376a867817eaf3d4b320 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:36 +0100 Subject: [PATCH 630/894] avdevice/dshow: discover source color range/space/etc Enabled discovering a DirectShow device's color range, space, primaries, transfer characteristics and chroma location, if the device exposes that information. Sets them in the stream's codecpars. Co-authored-by: Valerii Zapodovnikov Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 223 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 4b1e942c7a..55774cc3f0 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -29,6 +29,30 @@ #include "libavcodec/raw.h" #include "objidl.h" #include "shlwapi.h" +// NB: technically, we should include dxva.h and use +// DXVA_ExtendedFormat, but that type is not defined in +// the MinGW headers. The DXVA2_ExtendedFormat and the +// contents of its fields is identical to +// DXVA_ExtendedFormat (see https://docs.microsoft.com/en-us/windows/win32/medfound/extended-color-information#color-space-in-media-types) +// and is provided by MinGW as well, so we use that +// instead. NB also that per the Microsoft docs, the +// lowest 8 bits of the structure, i.e. the SampleFormat +// field, contain AMCONTROL_xxx flags instead of sample +// format information, and should thus not be used. +// NB further that various values in the structure's +// fields (e.g. BT.2020 color space) are not provided +// for either of the DXVA structs, but are provided in +// the flags of the corresponding fields of Media Foundation. +// These may be provided by DirectShow devices (e.g. LAVFilters +// does so). So we use those values here too (the equivalence is +// indicated by Microsoft example code: https://docs.microsoft.com/en-us/windows/win32/api/dxva2api/ns-dxva2api-dxva2_videodesc) +#include "d3d9types.h" +#include "dxva2api.h" + +#ifndef AMCONTROL_COLORINFO_PRESENT +// not defined in some versions of MinGW's dvdmedia.h +# define AMCONTROL_COLORINFO_PRESENT 0x00000080 // if set, indicates DXVA color info is present in the upper (24) bits of the dwControlFlags +#endif static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) @@ -54,6 +78,161 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others } +static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->NominalRange) + { + case DXVA2_NominalRange_Unknown: + return AVCOL_RANGE_UNSPECIFIED; + case DXVA2_NominalRange_Normal: // equal to DXVA2_NominalRange_0_255 + return AVCOL_RANGE_JPEG; + case DXVA2_NominalRange_Wide: // equal to DXVA2_NominalRange_16_235 + return AVCOL_RANGE_MPEG; + case DXVA2_NominalRange_48_208: + // not an ffmpeg color range + return AVCOL_RANGE_UNSPECIFIED; + + // values from MediaFoundation SDK (mfobjects.h) + case 4: // MFNominalRange_64_127 + // not an ffmpeg color range + return AVCOL_RANGE_UNSPECIFIED; + + default: + return AVCOL_RANGE_UNSPECIFIED; + } +} + +static enum AVColorSpace dshow_color_space(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->VideoTransferMatrix) + { + case DXVA2_VideoTransferMatrix_BT709: + return AVCOL_SPC_BT709; + case DXVA2_VideoTransferMatrix_BT601: + return AVCOL_SPC_BT470BG; + case DXVA2_VideoTransferMatrix_SMPTE240M: + return AVCOL_SPC_SMPTE240M; + + // values from MediaFoundation SDK (mfobjects.h) + case 4: // MFVideoTransferMatrix_BT2020_10 + case 5: // MFVideoTransferMatrix_BT2020_12 + if (fmt_info->VideoTransferFunction == 12) // MFVideoTransFunc_2020_const + return AVCOL_SPC_BT2020_CL; + else + return AVCOL_SPC_BT2020_NCL; + + default: + return AVCOL_SPC_UNSPECIFIED; + } +} + +static enum AVColorPrimaries dshow_color_primaries(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->VideoPrimaries) + { + case DXVA2_VideoPrimaries_Unknown: + return AVCOL_PRI_UNSPECIFIED; + case DXVA2_VideoPrimaries_reserved: + return AVCOL_PRI_RESERVED; + case DXVA2_VideoPrimaries_BT709: + return AVCOL_PRI_BT709; + case DXVA2_VideoPrimaries_BT470_2_SysM: + return AVCOL_PRI_BT470M; + case DXVA2_VideoPrimaries_BT470_2_SysBG: + case DXVA2_VideoPrimaries_EBU3213: // this is PAL + return AVCOL_PRI_BT470BG; + case DXVA2_VideoPrimaries_SMPTE170M: + case DXVA2_VideoPrimaries_SMPTE_C: + return AVCOL_PRI_SMPTE170M; + case DXVA2_VideoPrimaries_SMPTE240M: + return AVCOL_PRI_SMPTE240M; + + // values from MediaFoundation SDK (mfobjects.h) + case 9: // MFVideoPrimaries_BT2020 + return AVCOL_PRI_BT2020; + case 10: // MFVideoPrimaries_XYZ + return AVCOL_PRI_SMPTE428; + case 11: // MFVideoPrimaries_DCI_P3 + return AVCOL_PRI_SMPTE431; + case 12: // MFVideoPrimaries_ACES (Academy Color Encoding System) + // not an FFmpeg color primary + return AVCOL_PRI_UNSPECIFIED; + + default: + return AVCOL_PRI_UNSPECIFIED; + } +} + +static enum AVColorTransferCharacteristic dshow_color_trc(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->VideoTransferFunction) + { + case DXVA2_VideoTransFunc_Unknown: + return AVCOL_TRC_UNSPECIFIED; + case DXVA2_VideoTransFunc_10: + return AVCOL_TRC_LINEAR; + case DXVA2_VideoTransFunc_18: + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case DXVA2_VideoTransFunc_20: + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case DXVA2_VideoTransFunc_22: + return AVCOL_TRC_GAMMA22; + case DXVA2_VideoTransFunc_709: + return AVCOL_TRC_BT709; + case DXVA2_VideoTransFunc_240M: + return AVCOL_TRC_SMPTE240M; + case DXVA2_VideoTransFunc_sRGB: + return AVCOL_TRC_IEC61966_2_1; + case DXVA2_VideoTransFunc_28: + return AVCOL_TRC_GAMMA28; + + // values from MediaFoundation SDK (mfobjects.h) + case 9: // MFVideoTransFunc_Log_100 + return AVCOL_TRC_LOG; + case 10: // MFVideoTransFunc_Log_316 + return AVCOL_TRC_LOG_SQRT; + case 11: // MFVideoTransFunc_709_sym + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case 12: // MFVideoTransFunc_2020_const + case 13: // MFVideoTransFunc_2020 + if (fmt_info->VideoTransferMatrix == 5) // MFVideoTransferMatrix_BT2020_12 + return AVCOL_TRC_BT2020_12; + else + return AVCOL_TRC_BT2020_10; + case 14: // MFVideoTransFunc_26 + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case 15: // MFVideoTransFunc_2084 + return AVCOL_TRC_SMPTEST2084; + case 16: // MFVideoTransFunc_HLG + return AVCOL_TRC_ARIB_STD_B67; + case 17: // MFVideoTransFunc_10_rel + // not an FFmpeg transfer characteristic? Undocumented also by MS + return AVCOL_TRC_UNSPECIFIED; + + default: + return AVCOL_TRC_UNSPECIFIED; + } +} + +static enum AVChromaLocation dshow_chroma_loc(DXVA2_ExtendedFormat *fmt_info) +{ + if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_Cosited) // that is: (DXVA2_VideoChromaSubsampling_Horizontally_Cosited | DXVA2_VideoChromaSubsampling_Vertically_Cosited | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes) + return AVCHROMA_LOC_TOPLEFT; + else if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_MPEG1) // that is: DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes + return AVCHROMA_LOC_CENTER; + else if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_MPEG2) // that is: (DXVA2_VideoChromaSubsampling_Horizontally_Cosited | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes) + return AVCHROMA_LOC_LEFT; + else if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_DV_PAL) // that is: (DXVA2_VideoChromaSubsampling_Horizontally_Cosited | DXVA2_VideoChromaSubsampling_Vertically_Cosited) + return AVCHROMA_LOC_TOPLEFT; + else + // unknown + return AVCHROMA_LOC_UNSPECIFIED; +} + static int dshow_read_close(AVFormatContext *s) { @@ -517,6 +696,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, VIDEO_STREAM_CONFIG_CAPS *vcaps = caps; BITMAPINFOHEADER *bih; int64_t *fr; + DXVA2_ExtendedFormat *extended_format_info = NULL; const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; #if DSHOWDEBUG ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps); @@ -529,6 +709,8 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, VIDEOINFOHEADER2 *v = (void *) type->pbFormat; fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; + if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) + extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; } else { goto next; } @@ -545,11 +727,40 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, } else { av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt)); } - av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n", + av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g", vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy, 1e7 / vcaps->MaxFrameInterval, vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy, 1e7 / vcaps->MinFrameInterval); + if (extended_format_info) { + enum AVColorRange col_range = dshow_color_range(extended_format_info); + enum AVColorSpace col_space = dshow_color_space(extended_format_info); + enum AVColorPrimaries col_prim = dshow_color_primaries(extended_format_info); + enum AVColorTransferCharacteristic col_trc = dshow_color_trc(extended_format_info); + enum AVChromaLocation chroma_loc = dshow_chroma_loc(extended_format_info); + if (col_range != AVCOL_RANGE_UNSPECIFIED || col_space != AVCOL_SPC_UNSPECIFIED || col_prim != AVCOL_PRI_UNSPECIFIED || col_trc != AVCOL_TRC_UNSPECIFIED) { + const char *range = av_color_range_name(col_range); + const char *space = av_color_space_name(col_space); + const char *prim = av_color_primaries_name(col_prim); + const char *trc = av_color_transfer_name(col_trc); + av_log(avctx, AV_LOG_INFO, " (%s, %s/%s/%s", + range ? range : "unknown", + space ? space : "unknown", + prim ? prim : "unknown", + trc ? trc : "unknown"); + if (chroma_loc != AVCHROMA_LOC_UNSPECIFIED) { + const char *chroma = av_chroma_location_name(chroma_loc); + av_log(avctx, AV_LOG_INFO, ", %s", chroma ? chroma : "unknown"); + } + av_log(avctx, AV_LOG_INFO, ")"); + } + else if (chroma_loc != AVCHROMA_LOC_UNSPECIFIED) { + const char *chroma = av_chroma_location_name(chroma_loc); + av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown"); + } + } + + av_log(avctx, AV_LOG_INFO, "\n"); continue; } if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) { @@ -1118,6 +1329,7 @@ dshow_add_device(AVFormatContext *avctx, if (devtype == VideoDevice) { BITMAPINFOHEADER *bih = NULL; AVRational time_base; + DXVA2_ExtendedFormat *extended_format_info = NULL; if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type.pbFormat; @@ -1127,6 +1339,8 @@ dshow_add_device(AVFormatContext *avctx, VIDEOINFOHEADER2 *v = (void *) type.pbFormat; time_base = (AVRational) { v->AvgTimePerFrame, 10000000 }; bih = &v->bmiHeader; + if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) + extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; } if (!bih) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); @@ -1145,6 +1359,13 @@ dshow_add_device(AVFormatContext *avctx, av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n"); par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this... } + if (extended_format_info) { + par->color_range = dshow_color_range(extended_format_info); + par->color_space = dshow_color_space(extended_format_info); + par->color_primaries = dshow_color_primaries(extended_format_info); + par->color_trc = dshow_color_trc(extended_format_info); + par->chroma_location = dshow_chroma_loc(extended_format_info); + } if (par->format == AV_PIX_FMT_NONE) { const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; par->codec_id = av_codec_get_id(tags, bih->biCompression); From a1c4929f65cc75b7175622a007b1e4bd37043d41 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 21 Dec 2021 14:53:37 +0100 Subject: [PATCH 631/894] avdevice/dshow: select format with extended color info Some DirectShow devices (Logitech C920 webcam) expose each DirectShow format they support twice, once without and once with extended color information. During format selection, both match, this patch ensures that the format with extended color information is selected if it is available, else it falls back to a matching format without such information. This also necessitated a new code path taken for default formats of a device (when user didn't request any specific video size, etc), because the default format may be one without extended color information when a twin with extended color information is also available. Getting the extended color information when available is important as it allows setting the color space, range, primaries, transfer characteristics and chroma location of the stream provided by dshow, enabling users to get more correct color automatically out of their device. Closes: #9271 Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 471 ++++++++++++++++++++++++++++++++------------ 1 file changed, 340 insertions(+), 131 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 55774cc3f0..671393f468 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -23,6 +23,7 @@ #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/mem.h" #include "libavformat/internal.h" #include "libavformat/riff.h" #include "avdevice.h" @@ -658,9 +659,111 @@ error: return ret; } +static int dshow_should_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype) +{ + struct dshow_ctx *ctx = avctx->priv_data; + + return (devtype == VideoDevice && (ctx->framerate || + (ctx->requested_width && ctx->requested_height) || + ctx->pixel_format != AV_PIX_FMT_NONE || + ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) + || (devtype == AudioDevice && (ctx->channels || ctx->sample_size || ctx->sample_rate)); +} + + +struct dshow_format_info { + enum dshowDeviceType devtype; + // video + int64_t framerate; + enum AVPixelFormat pix_fmt; + enum AVCodecID codec_id; + enum AVColorRange col_range; + enum AVColorSpace col_space; + enum AVColorPrimaries col_prim; + enum AVColorTransferCharacteristic col_trc; + enum AVChromaLocation chroma_loc; + int width; + int height; + // audio + int sample_rate; + int sample_size; + int channels; +}; + +// user must av_free the returned pointer +static struct dshow_format_info *dshow_get_format_info(AM_MEDIA_TYPE *type) +{ + struct dshow_format_info *fmt_info = NULL; + BITMAPINFOHEADER *bih; + DXVA2_ExtendedFormat *extended_format_info = NULL; + WAVEFORMATEX *fx; + enum dshowDeviceType devtype; + int64_t framerate; + + if (!type) + return NULL; + + if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) { + VIDEOINFOHEADER *v = (void *) type->pbFormat; + framerate = v->AvgTimePerFrame; + bih = &v->bmiHeader; + devtype = VideoDevice; + } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) { + VIDEOINFOHEADER2 *v = (void *) type->pbFormat; + devtype = VideoDevice; + framerate = v->AvgTimePerFrame; + bih = &v->bmiHeader; + if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) + extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; + } else if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) { + fx = (void *) type->pbFormat; + devtype = AudioDevice; + } else { + return NULL; + } + + fmt_info = av_mallocz(sizeof(struct dshow_format_info)); + if (!fmt_info) + return NULL; + // initialize fields where unset is not zero + fmt_info->pix_fmt = AV_PIX_FMT_NONE; + fmt_info->col_space = AVCOL_SPC_UNSPECIFIED; + fmt_info->col_prim = AVCOL_PRI_UNSPECIFIED; + fmt_info->col_trc = AVCOL_TRC_UNSPECIFIED; + // now get info about format + fmt_info->devtype = devtype; + if (devtype == VideoDevice) { + fmt_info->width = bih->biWidth; + fmt_info->height = bih->biHeight; + fmt_info->framerate = framerate; + fmt_info->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); + if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) { + const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; + fmt_info->codec_id = av_codec_get_id(tags, bih->biCompression); + } + else + fmt_info->codec_id = AV_CODEC_ID_RAWVIDEO; + + if (extended_format_info) { + fmt_info->col_range = dshow_color_range(extended_format_info); + fmt_info->col_space = dshow_color_space(extended_format_info); + fmt_info->col_prim = dshow_color_primaries(extended_format_info); + fmt_info->col_trc = dshow_color_trc(extended_format_info); + fmt_info->chroma_loc = dshow_chroma_loc(extended_format_info); + } + } else { + fmt_info->sample_rate = fx->nSamplesPerSec; + fmt_info->sample_size = fx->wBitsPerSample; + fmt_info->channels = fx->nChannels; + } + + return fmt_info; +} + /** - * Cycle through available formats using the specified pin, - * try to set parameters specified through AVOptions and if successful + * Cycle through available formats available from the specified pin, + * try to set parameters specified through AVOptions, or the pin's + * default format if no such parameters were set. If successful, * return 1 in *pformat_set. * If pformat_set is NULL, list all pin capabilities. */ @@ -671,9 +774,27 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, struct dshow_ctx *ctx = avctx->priv_data; IAMStreamConfig *config = NULL; AM_MEDIA_TYPE *type = NULL; + AM_MEDIA_TYPE *previous_match_type = NULL; int format_set = 0; void *caps = NULL; int i, n, size, r; + int wait_for_better = 0; + int use_default; + + // format parameters requested by user + // if none are requested by user, the values will below be set to + // those of the default format + // video + enum AVCodecID requested_video_codec_id = ctx->video_codec_id; + enum AVPixelFormat requested_pixel_format = ctx->pixel_format; + int64_t requested_framerate = ctx->framerate ? ((int64_t)ctx->requested_framerate.den * 10000000) + / ctx->requested_framerate.num : 0; + int requested_width = ctx->requested_width; + int requested_height = ctx->requested_height; + // audio + int requested_sample_rate = ctx->sample_rate; + int requested_sample_size = ctx->sample_size; + int requested_channels = ctx->channels; if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK) return; @@ -684,7 +805,83 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, if (!caps) goto end; + /** + * If we should open the device with the default format, + * then: + * 1. check what the format of the default device is, and + * 2. below we iterate all formats till we find a matching + * one, with most info exposed (see comment below). + */ + use_default = !dshow_should_set_format(avctx, devtype); + if (use_default && pformat_set) + { + HRESULT hr; + + // get default + if ((hr = IAMStreamConfig_GetFormat(config, &type)) != S_OK) { + if (hr == E_NOTIMPL || !IsEqualGUID(&type->majortype, devtype==VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + // default not available or of wrong type, + // fall back to iterating exposed formats + // until one of the right type is found + IEnumMediaTypes *types = NULL; + if (IPin_EnumMediaTypes(pin, &types) != S_OK) + goto end; + IEnumMediaTypes_Reset(types); + while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { + if (IsEqualGUID(&type->majortype, devtype==VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + break; + } + CoTaskMemFree(type); + type = NULL; + } + IEnumMediaTypes_Release(types); + } + + if (!type) + // this pin does not expose any formats of the expected type + goto end; + } + + if (type) { + // interrogate default format, so we know what to search for below + struct dshow_format_info *fmt_info = dshow_get_format_info(type); + if (fmt_info) { + if (fmt_info->devtype == VideoDevice) { + requested_video_codec_id = fmt_info->codec_id; + requested_pixel_format = fmt_info->pix_fmt; + requested_framerate = fmt_info->framerate; + requested_width = fmt_info->width; + requested_height = fmt_info->height; + } else { + requested_sample_rate = fmt_info->sample_rate; + requested_sample_size = fmt_info->sample_size; + requested_channels = fmt_info->channels; + } + av_free(fmt_info); // free but don't set to NULL to enable below check + } + + if (type && type->pbFormat) + CoTaskMemFree(type->pbFormat); + CoTaskMemFree(type); + type = NULL; + if (!fmt_info) + // default format somehow invalid, can't continue with this pin + goto end; + fmt_info = NULL; + } + } + + // NB: some devices (e.g. Logitech C920) expose each video format twice: + // both a format containing a VIDEOINFOHEADER and a format containing + // a VIDEOINFOHEADER2. We want, if possible, to select a format with a + // VIDEOINFOHEADER2, as this potentially provides more info about the + // format. So, if in the iteration below we have found a matching format, + // but it is a VIDEOINFOHEADER, keep looking for a matching format that + // exposes contains a VIDEOINFOHEADER2. Fall back to the VIDEOINFOHEADER + // format if no corresponding VIDEOINFOHEADER2 is found when we finish + // iterating. for (i = 0; i < n && !format_set; i++) { + struct dshow_format_info *fmt_info = NULL; r = IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps); if (r != S_OK) goto next; @@ -692,106 +889,101 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, ff_print_AM_MEDIA_TYPE(type); #endif + fmt_info = dshow_get_format_info(type); + if (!fmt_info) + goto next; + if (devtype == VideoDevice) { VIDEO_STREAM_CONFIG_CAPS *vcaps = caps; BITMAPINFOHEADER *bih; int64_t *fr; - DXVA2_ExtendedFormat *extended_format_info = NULL; - const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; #if DSHOWDEBUG ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps); #endif + + if (fmt_info->devtype != VideoDevice) + goto next; + if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type->pbFormat; - fr = &v->AvgTimePerFrame; + fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; + wait_for_better = 1; } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) { VIDEOINFOHEADER2 *v = (void *) type->pbFormat; - fr = &v->AvgTimePerFrame; + fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; - if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) - extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; - } else { - goto next; + wait_for_better = 0; } + if (!pformat_set) { - enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); - if (pix_fmt == AV_PIX_FMT_NONE) { - enum AVCodecID codec_id = av_codec_get_id(tags, bih->biCompression); - const AVCodec *codec = avcodec_find_decoder(codec_id); - if (codec_id == AV_CODEC_ID_NONE || !codec) { + if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) { + const AVCodec *codec = avcodec_find_decoder(fmt_info->codec_id); + if (fmt_info->codec_id == AV_CODEC_ID_NONE || !codec) { av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression); } else { av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name); } } else { - av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt)); + av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(fmt_info->pix_fmt)); } av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g", vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy, 1e7 / vcaps->MaxFrameInterval, vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy, 1e7 / vcaps->MinFrameInterval); - if (extended_format_info) { - enum AVColorRange col_range = dshow_color_range(extended_format_info); - enum AVColorSpace col_space = dshow_color_space(extended_format_info); - enum AVColorPrimaries col_prim = dshow_color_primaries(extended_format_info); - enum AVColorTransferCharacteristic col_trc = dshow_color_trc(extended_format_info); - enum AVChromaLocation chroma_loc = dshow_chroma_loc(extended_format_info); - if (col_range != AVCOL_RANGE_UNSPECIFIED || col_space != AVCOL_SPC_UNSPECIFIED || col_prim != AVCOL_PRI_UNSPECIFIED || col_trc != AVCOL_TRC_UNSPECIFIED) { - const char *range = av_color_range_name(col_range); - const char *space = av_color_space_name(col_space); - const char *prim = av_color_primaries_name(col_prim); - const char *trc = av_color_transfer_name(col_trc); - av_log(avctx, AV_LOG_INFO, " (%s, %s/%s/%s", - range ? range : "unknown", - space ? space : "unknown", - prim ? prim : "unknown", - trc ? trc : "unknown"); - if (chroma_loc != AVCHROMA_LOC_UNSPECIFIED) { - const char *chroma = av_chroma_location_name(chroma_loc); - av_log(avctx, AV_LOG_INFO, ", %s", chroma ? chroma : "unknown"); - } - av_log(avctx, AV_LOG_INFO, ")"); - } - else if (chroma_loc != AVCHROMA_LOC_UNSPECIFIED) { - const char *chroma = av_chroma_location_name(chroma_loc); - av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown"); - } + + const char *chroma = av_chroma_location_name(fmt_info->chroma_loc); + if (fmt_info->col_range != AVCOL_RANGE_UNSPECIFIED || + fmt_info->col_space != AVCOL_SPC_UNSPECIFIED || + fmt_info->col_prim != AVCOL_PRI_UNSPECIFIED || + fmt_info->col_trc != AVCOL_TRC_UNSPECIFIED) { + const char *range = av_color_range_name(fmt_info->col_range); + const char *space = av_color_space_name(fmt_info->col_space); + const char *prim = av_color_primaries_name(fmt_info->col_prim); + const char *trc = av_color_transfer_name(fmt_info->col_trc); + av_log(avctx, AV_LOG_INFO, " (%s, %s/%s/%s", + range ? range : "unknown", + space ? space : "unknown", + prim ? prim : "unknown", + trc ? trc : "unknown"); + if (fmt_info->chroma_loc != AVCHROMA_LOC_UNSPECIFIED) + av_log(avctx, AV_LOG_INFO, ", %s", chroma ? chroma : "unknown"); + av_log(avctx, AV_LOG_INFO, ")"); } + else if (fmt_info->chroma_loc != AVCHROMA_LOC_UNSPECIFIED) + av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown"); av_log(avctx, AV_LOG_INFO, "\n"); continue; } - if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) { - if (ctx->video_codec_id != av_codec_get_id(tags, bih->biCompression)) + if (requested_video_codec_id != AV_CODEC_ID_RAWVIDEO) { + if (requested_video_codec_id != fmt_info->codec_id) goto next; } - if (ctx->pixel_format != AV_PIX_FMT_NONE && - ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) { + if (requested_pixel_format != AV_PIX_FMT_NONE && + requested_pixel_format != fmt_info->pix_fmt) { goto next; } - if (ctx->framerate) { - int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000) - / ctx->requested_framerate.num; - if (framerate > vcaps->MaxFrameInterval || - framerate < vcaps->MinFrameInterval) + if (requested_framerate) { + if (requested_framerate > vcaps->MaxFrameInterval || + requested_framerate < vcaps->MinFrameInterval) goto next; - *fr = framerate; + *fr = requested_framerate; } - if (ctx->requested_width && ctx->requested_height) { - if (ctx->requested_width > vcaps->MaxOutputSize.cx || - ctx->requested_width < vcaps->MinOutputSize.cx || - ctx->requested_height > vcaps->MaxOutputSize.cy || - ctx->requested_height < vcaps->MinOutputSize.cy) + if (requested_width && requested_height) { + if (requested_width > vcaps->MaxOutputSize.cx || + requested_width < vcaps->MinOutputSize.cx || + requested_height > vcaps->MaxOutputSize.cy || + requested_height < vcaps->MinOutputSize.cy) goto next; - bih->biWidth = ctx->requested_width; - bih->biHeight = ctx->requested_height; + bih->biWidth = requested_width; + bih->biHeight = requested_height; } } else { WAVEFORMATEX *fx; -#if DSHOWDEBUG AUDIO_STREAM_CONFIG_CAPS *acaps = caps; +#if DSHOWDEBUG ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps); #endif if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) { @@ -808,23 +1000,62 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, ); continue; } - if ( - (ctx->sample_rate && ctx->sample_rate != fx->nSamplesPerSec) || - (ctx->sample_size && ctx->sample_size != fx->wBitsPerSample) || - (ctx->channels && ctx->channels != fx->nChannels ) - ) { - goto next; + if (requested_sample_rate) { + if (requested_sample_rate > acaps->MaximumSampleFrequency || + requested_sample_rate < acaps->MinimumSampleFrequency) + goto next; + fx->nSamplesPerSec = requested_sample_rate; + } + if (requested_sample_size) { + if (requested_sample_size > acaps->MaximumBitsPerSample || + requested_sample_size < acaps->MinimumBitsPerSample) + goto next; + fx->wBitsPerSample = requested_sample_size; + } + if (requested_channels) { + if (requested_channels > acaps->MaximumChannels || + requested_channels < acaps->MinimumChannels) + goto next; + fx->nChannels = requested_channels; } } - if (IAMStreamConfig_SetFormat(config, type) != S_OK) - goto next; - format_set = 1; + + // found a matching format. Either apply or store + // for safekeeping if we might maybe find a better + // format with more info attached to it (see comment + // above loop) + if (!wait_for_better) { + if (IAMStreamConfig_SetFormat(config, type) != S_OK) + goto next; + format_set = 1; + } + else if (!previous_match_type) { + // store this matching format for possible later use. + // If we have already found a matching format, ignore it + previous_match_type = type; + type = NULL; + } next: - if (type->pbFormat) + av_freep(&fmt_info); + if (type && type->pbFormat) CoTaskMemFree(type->pbFormat); CoTaskMemFree(type); } + // previously found a matching VIDEOINFOHEADER format and stored + // it for safe keeping. Searching further for a matching + // VIDEOINFOHEADER2 format yielded nothing. So set the pin's + // format based on the VIDEOINFOHEADER format. + // NB: this never applies to an audio format because + // previous_match_type always NULL in that case + if (!format_set && previous_match_type) { + if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) + format_set = 1; + } + end: + if (previous_match_type && previous_match_type->pbFormat) + CoTaskMemFree(previous_match_type->pbFormat); + CoTaskMemFree(previous_match_type); IAMStreamConfig_Release(config); av_free(caps); if (pformat_set) @@ -943,11 +1174,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only"; const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio"; - int set_format = (devtype == VideoDevice && (ctx->framerate || - (ctx->requested_width && ctx->requested_height) || - ctx->pixel_format != AV_PIX_FMT_NONE || - ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) - || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate || ctx->sample_size)); + int set_format = dshow_should_set_format(avctx, devtype); int format_set = 0; int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog; @@ -967,9 +1194,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { IKsPropertySet *p = NULL; - IEnumMediaTypes *types = NULL; PIN_INFO info = {0}; - AM_MEDIA_TYPE *type; GUID category; DWORD r2; char *name_buf = NULL; @@ -1012,35 +1237,24 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, } } - if (set_format) { - dshow_cycle_formats(avctx, devtype, pin, &format_set); - if (!format_set) { - goto next; - } + // will either try to find format matching options supplied by user + // or try to open default format. Successful if returns with format_set==1 + dshow_cycle_formats(avctx, devtype, pin, &format_set); + if (!format_set) { + goto next; } + if (devtype == AudioDevice && ctx->audio_buffer_size) { if (dshow_set_audio_buffer_size(avctx, pin) < 0) { av_log(avctx, AV_LOG_ERROR, "unable to set audio buffer size %d to pin, using pin anyway...", ctx->audio_buffer_size); } } - if (IPin_EnumMediaTypes(pin, &types) != S_OK) - goto next; - - IEnumMediaTypes_Reset(types); - /* in case format_set was not called, just verify the majortype */ - while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { - if (IsEqualGUID(&type->majortype, mediatype[devtype])) { - device_pin = pin; - av_log(avctx, AV_LOG_DEBUG, "Selecting pin %s on %s\n", name_buf, devtypename); - goto next; - } - CoTaskMemFree(type); + if (format_set) { + device_pin = pin; + av_log(avctx, AV_LOG_DEBUG, "Selecting pin %s on %s\n", name_buf, devtypename); } - next: - if (types) - IEnumMediaTypes_Release(types); if (p) IKsPropertySet_Release(p); if (device_pin != pin) @@ -1310,6 +1524,7 @@ dshow_add_device(AVFormatContext *avctx, AM_MEDIA_TYPE type; AVCodecParameters *par; AVStream *st; + struct dshow_format_info *fmt_info = NULL; int ret = AVERROR(EIO); type.pbFormat = NULL; @@ -1324,12 +1539,16 @@ dshow_add_device(AVFormatContext *avctx, ctx->capture_filter[devtype]->stream_index = st->index; ff_dshow_pin_ConnectionMediaType(ctx->capture_pin[devtype], &type); + fmt_info = dshow_get_format_info(&type); + if (!fmt_info) { + ret = AVERROR(EIO); + goto error; + } par = st->codecpar; if (devtype == VideoDevice) { BITMAPINFOHEADER *bih = NULL; AVRational time_base; - DXVA2_ExtendedFormat *extended_format_info = NULL; if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type.pbFormat; @@ -1339,8 +1558,6 @@ dshow_add_device(AVFormatContext *avctx, VIDEOINFOHEADER2 *v = (void *) type.pbFormat; time_base = (AVRational) { v->AvgTimePerFrame, 10000000 }; bih = &v->bmiHeader; - if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) - extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; } if (!bih) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); @@ -1351,33 +1568,21 @@ dshow_add_device(AVFormatContext *avctx, st->r_frame_rate = av_inv_q(time_base); par->codec_type = AVMEDIA_TYPE_VIDEO; - par->width = bih->biWidth; - par->height = bih->biHeight; + par->width = fmt_info->width; + par->height = fmt_info->height; par->codec_tag = bih->biCompression; - par->format = dshow_pixfmt(bih->biCompression, bih->biBitCount); + par->format = fmt_info->pix_fmt; if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) { av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n"); par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this... } - if (extended_format_info) { - par->color_range = dshow_color_range(extended_format_info); - par->color_space = dshow_color_space(extended_format_info); - par->color_primaries = dshow_color_primaries(extended_format_info); - par->color_trc = dshow_color_trc(extended_format_info); - par->chroma_location = dshow_chroma_loc(extended_format_info); - } - if (par->format == AV_PIX_FMT_NONE) { - const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; - par->codec_id = av_codec_get_id(tags, bih->biCompression); - if (par->codec_id == AV_CODEC_ID_NONE) { - av_log(avctx, AV_LOG_ERROR, "Unknown compression type. " - "Please report type 0x%X.\n", (int) bih->biCompression); - ret = AVERROR_PATCHWELCOME; - goto error; - } - par->bits_per_coded_sample = bih->biBitCount; - } else { - par->codec_id = AV_CODEC_ID_RAWVIDEO; + par->color_range = fmt_info->col_range; + par->color_space = fmt_info->col_space; + par->color_primaries = fmt_info->col_prim; + par->color_trc = fmt_info->col_trc; + par->chroma_location = fmt_info->chroma_loc; + par->codec_id = fmt_info->codec_id; + if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) { par->bits_per_coded_sample = bih->biBitCount; if (par->height < 0) { @@ -1390,23 +1595,26 @@ dshow_add_device(AVFormatContext *avctx, } } } + } else { + if (par->codec_id == AV_CODEC_ID_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unknown compression type. " + "Please report type 0x%X.\n", (int) bih->biCompression); + ret = AVERROR_PATCHWELCOME; + goto error; + } + par->bits_per_coded_sample = bih->biBitCount; } } else { - WAVEFORMATEX *fx = NULL; - - if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) { - fx = (void *) type.pbFormat; - } - if (!fx) { + if (!IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); goto error; } par->codec_type = AVMEDIA_TYPE_AUDIO; - par->format = sample_fmt_bits_per_sample(fx->wBitsPerSample); + par->format = sample_fmt_bits_per_sample(fmt_info->sample_size); par->codec_id = waveform_codec_id(par->format); - par->sample_rate = fx->nSamplesPerSec; - par->channels = fx->nChannels; + par->sample_rate = fmt_info->sample_rate; + par->channels = fmt_info->channels; } avpriv_set_pts_info(st, 64, 1, 10000000); @@ -1414,6 +1622,7 @@ dshow_add_device(AVFormatContext *avctx, ret = 0; error: + av_freep(&fmt_info); if (type.pbFormat) CoTaskMemFree(type.pbFormat); return ret; From c147f7962c2a6634608531bdd14052e836bc860c Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Dec 2021 14:23:01 -0300 Subject: [PATCH 632/894] avdevice/dshow: remove unused variables Signed-off-by: James Almer --- libavdevice/dshow.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 671393f468..0929ad9316 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -382,7 +382,6 @@ dshow_get_device_media_types(AVFormatContext *avctx, enum dshowDeviceType devtyp enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, enum AVMediaType **media_types, int *nb_media_types) { - struct dshow_ctx *ctx = avctx->priv_data; IEnumPins *pins = 0; IPin *pin; int has_audio = 0, has_video = 0; @@ -628,7 +627,6 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, static int dshow_get_device_list(AVFormatContext *avctx, AVDeviceInfoList *device_list) { - struct dshow_ctx *ctx = avctx->priv_data; ICreateDevEnum *devenum = NULL; int r; int ret = AVERROR(EIO); @@ -1170,7 +1168,6 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, IPin *pin; int r; - const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio }; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only"; const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio"; From 2497a45562f6439f7d0002319d53d925f0c51535 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Dec 2021 14:24:07 -0300 Subject: [PATCH 633/894] avdevice/dshow: don't mix declarations and code Signed-off-by: James Almer --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 0929ad9316..30f1be1ead 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -915,6 +915,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, } if (!pformat_set) { + const char *chroma = av_chroma_location_name(fmt_info->chroma_loc); if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) { const AVCodec *codec = avcodec_find_decoder(fmt_info->codec_id); if (fmt_info->codec_id == AV_CODEC_ID_NONE || !codec) { @@ -931,7 +932,6 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy, 1e7 / vcaps->MinFrameInterval); - const char *chroma = av_chroma_location_name(fmt_info->chroma_loc); if (fmt_info->col_range != AVCOL_RANGE_UNSPECIFIED || fmt_info->col_space != AVCOL_SPC_UNSPECIFIED || fmt_info->col_prim != AVCOL_PRI_UNSPECIFIED || From 209488ccb0f38fbb384a4821f8c170986255d21b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 18 Dec 2021 16:04:40 +0100 Subject: [PATCH 634/894] avfilter: add anlmf filter --- Changelog | 1 + doc/filters.texi | 4 ++-- libavfilter/Makefile | 1 + libavfilter/af_anlms.c | 22 +++++++++++++++++++++- libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Changelog b/Changelog index a613e2c5a6..edb4152d0f 100644 --- a/Changelog +++ b/Changelog @@ -43,6 +43,7 @@ version : - adynamicequalizer audio filter - yadif_videotoolbox filter - VideoToolbox ProRes encoder +- anlmf audio filter version 4.4: diff --git a/doc/filters.texi b/doc/filters.texi index da95688c53..05d4b1a56e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2301,8 +2301,8 @@ Set smooth factor. Default value is @var{11}. Allowed range is from @var{1} to @ This filter supports the all above options as @ref{commands}. -@section anlms -Apply Normalized Least-Mean-Squares algorithm to the first audio stream using the second audio stream. +@section anlmf, anlms +Apply Normalized Least-Mean-(Squares|Fourth) algorithm to the first audio stream using the second audio stream. This adaptive filter is used to mimic a desired filter by finding the filter coefficients that relate to producing the least mean square of the error signal (difference between the desired, diff --git a/libavfilter/Makefile b/libavfilter/Makefile index cb328c2bf8..090944a99c 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -71,6 +71,7 @@ OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o OBJS-$(CONFIG_AMULTIPLY_FILTER) += af_amultiply.o OBJS-$(CONFIG_ANEQUALIZER_FILTER) += af_anequalizer.o OBJS-$(CONFIG_ANLMDN_FILTER) += af_anlmdn.o +OBJS-$(CONFIG_ANLMF_FILTER) += af_anlms.o OBJS-$(CONFIG_ANLMS_FILTER) += af_anlms.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o OBJS-$(CONFIG_APAD_FILTER) += af_apad.o diff --git a/libavfilter/af_anlms.c b/libavfilter/af_anlms.c index f1f82b491d..f20e3c0e82 100644 --- a/libavfilter/af_anlms.c +++ b/libavfilter/af_anlms.c @@ -54,6 +54,8 @@ typedef struct AudioNLMSContext { AVFrame *frame[2]; + int anlmf; + AVFloatDSPContext *fdsp; } AudioNLMSContext; @@ -74,7 +76,7 @@ static const AVOption anlms_options[] = { { NULL } }; -AVFILTER_DEFINE_CLASS(anlms); +AVFILTER_DEFINE_CLASS_EXT(anlms, "anlm(f|s)", anlms_options); static int query_formats(AVFilterContext *ctx) { @@ -130,6 +132,8 @@ static float process_sample(AudioNLMSContext *s, float input, float desired, norm = s->eps + sum; b = mu * e / norm; + if (s->anlmf) + b *= 4.f * e * e; memcpy(tmp, delay + offset, order * sizeof(float)); @@ -241,6 +245,7 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AudioNLMSContext *s = ctx->priv; + s->anlmf = !strcmp(ctx->filter->name, "anlmf"); s->kernel_size = FFALIGN(s->order, 16); if (!s->offset) @@ -312,3 +317,18 @@ const AVFilter ff_af_anlms = { .flags = AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; + +const AVFilter ff_af_anlmf = { + .name = "anlmf", + .description = NULL_IF_CONFIG_SMALL("Apply Normalized Least-Mean-Fourth algorithm to first audio stream."), + .priv_size = sizeof(AudioNLMSContext), + .priv_class = &anlms_class, + .init = init, + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_QUERY_FUNC(query_formats), + .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 26f1c73505..caa755320e 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -64,6 +64,7 @@ extern const AVFilter ff_af_amix; extern const AVFilter ff_af_amultiply; extern const AVFilter ff_af_anequalizer; extern const AVFilter ff_af_anlmdn; +extern const AVFilter ff_af_anlmf; extern const AVFilter ff_af_anlms; extern const AVFilter ff_af_anull; extern const AVFilter ff_af_apad; diff --git a/libavfilter/version.h b/libavfilter/version.h index 0253c911be..a4066fd883 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 20 +#define LIBAVFILTER_VERSION_MINOR 21 #define LIBAVFILTER_VERSION_MICRO 100 From 10add8bb66b7c9d5999aa5b5a37eef3df27e934a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Dec 2021 20:20:08 +0100 Subject: [PATCH 635/894] avcodec/cdgraphics: avoid signed overflow in alpha Fixes: left shift of 255 by 24 places cannot be represented in type 'int' Fixes: 42766/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CDGRAPHICS_fuzzer-5142826105569280 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Andreas Rheinhardt Signed-off-by: Michael Niedermayer --- libavcodec/cdgraphics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index 06f8392094..a83babdf1e 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -122,7 +122,7 @@ static void cdg_load_palette(CDGraphicsContext *cc, uint8_t *data, int low) r = ((color >> 8) & 0x000F) * 17; g = ((color >> 4) & 0x000F) * 17; b = ((color ) & 0x000F) * 17; - palette[i + array_offset] = cc->alpha[i + array_offset] << 24 | r << 16 | g << 8 | b; + palette[i + array_offset] = (uint32_t)cc->alpha[i + array_offset] << 24 | r << 16 | g << 8 | b; } cc->frame->palette_has_changed = 1; } From f3a949dc4c6f01f43d502cbe2a7c06fe95114c79 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Dec 2021 20:43:47 +0100 Subject: [PATCH 636/894] avformat/mvdec: Check bytes_per_sample Fixes: division by zero Fixes: 42814/clusterfuzz-testcase-minimized-ffmpeg_dem_MV_fuzzer-4787014237552640 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Peter Ross Reviewed-by: John-Paul Stewart Signed-off-by: Michael Niedermayer --- libavformat/mvdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 1a5012e507..ea955d2b11 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -366,6 +366,9 @@ static int mv_read_header(AVFormatContext *avctx) avpriv_request_sample(avctx, "Audio compression (format %i)", v); } + if (bytes_per_sample == 0) + return AVERROR_INVALIDDATA; + if (set_channels(avctx, ast, avio_rb32(pb)) < 0) return AVERROR_INVALIDDATA; From 0c8741f819018c9a0820d7272052de4a43cd6f95 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 24 Dec 2021 12:32:47 +0800 Subject: [PATCH 637/894] avcodec/nvenc: add udu_sei option to import user data unregistered SEIs Signed-off-by: Limin Wang Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 3 +++ libavcodec/nvenc.h | 1 + libavcodec/nvenc_h264.c | 2 ++ libavcodec/nvenc_hevc.c | 2 ++ libavcodec/version.h | 2 +- 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index edc46ed33a..31dfed9241 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -2217,6 +2217,9 @@ static int prepare_sei_data_array(AVCodecContext *avctx, const AVFrame *frame) } } + if (!ctx->udu_sei) + return sei_count; + for (i = 0; i < frame->nb_side_data; i++) { AVFrameSideData *side_data = frame->side_data[i]; void *tmp; diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 08531e1be3..b42a156c56 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -235,6 +235,7 @@ typedef struct NvencContext int intra_refresh; int single_slice_intra_refresh; int constrained_encoding; + int udu_sei; } NvencContext; int ff_nvenc_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 7d78aa0d87..89e9a043fc 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -188,6 +188,8 @@ static const AVOption options[] = { #endif { "extra_sei", "Pass on extra SEI data (e.g. a53 cc) to be included in the bitstream", OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "udu_sei", "Pass on user data unregistered SEI if available", + OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "intra-refresh","Use Periodic Intra Refresh instead of IDR frames", OFFSET(intra_refresh),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "single-slice-intra-refresh", "Use single slice intra refresh", diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index a13ac5a395..c2c13bb210 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -169,6 +169,8 @@ static const AVOption options[] = { #endif { "extra_sei", "Pass on extra SEI data (e.g. a53 cc) to be included in the bitstream", OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "udu_sei", "Pass on user data unregistered SEI if available", + OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "intra-refresh","Use Periodic Intra Refresh instead of IDR frames", OFFSET(intra_refresh),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "single-slice-intra-refresh", "Use single slice intra refresh", diff --git a/libavcodec/version.h b/libavcodec/version.h index db71fb1130..580b099b36 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 59 #define LIBAVCODEC_VERSION_MINOR 15 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 1cbeac0c2f7e15add5fed0a306f63a87b330c0a1 Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Tue, 14 Dec 2021 16:27:42 +0100 Subject: [PATCH 638/894] avformat/mxfenc: fix DNxHD GC container_ul MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Gaullier Reviewed-by: Matthieu Bouron Reviewed-by: Tomas Härdin Signed-off-by: Marton Balint --- libavformat/mxfenc.c | 2 +- tests/ref/lavf/mxf_opatom | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 1cdfc07382..ec0ea7ee70 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -180,7 +180,7 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x00,0x00,0x00 }, mxf_write_cdci_desc }, // DNxHD - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 }, mxf_write_cdci_desc }, diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index 61e755550b..b818f26c36 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -5d235c127ace64b1f4fe6c79a7ca8be6 *tests/data/lavf/lavf.mxf_opatom +e558e50a94d88762e07ab8149aced7b9 *tests/data/lavf/lavf.mxf_opatom 4717625 tests/data/lavf/lavf.mxf_opatom tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a From dd7c0bc4f981f7113d7bef267cc1eca8d9fb10f1 Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Tue, 14 Dec 2021 16:27:43 +0100 Subject: [PATCH 639/894] avformat/mxfenc: fix DNxHD GC element_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The values for the essence element type were updated in the spec from 0x05/0x06 (ST2019-4 2008) to 0x0C/0x0D (ST2019-4 2009). Fixes ticket #6380. Thanks-to: Philip de Nier Thanks-to: Matthieu Bouron Reviewed-by: Matthieu Bouron Reviewed-by: Tomas Härdin Signed-off-by: Nicolas Gaullier Signed-off-by: Marton Balint --- libavformat/mxfenc.c | 9 ++++++++- tests/ref/lavf/mxf_opatom | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index ec0ea7ee70..873d64a5fd 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -32,6 +32,7 @@ * SMPTE 379M MXF Generic Container * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container * SMPTE 422M Mapping JPEG 2000 Codestreams into the MXF Generic Container + * SMPTE ST2019-4 (2009 or later) Mapping VC-3 Coding Units into the MXF Generic Container * SMPTE RP210: SMPTE Metadata Dictionary * SMPTE RP224: Registry of SMPTE Universal Labels */ @@ -181,7 +182,7 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { mxf_write_cdci_desc }, // DNxHD { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 }, + { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x0C,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 }, mxf_write_cdci_desc }, // JPEG2000 @@ -2674,6 +2675,12 @@ static int mxf_init(AVFormatContext *s) memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15); sc->track_essence_element_key[15] = present[sc->index]; + if (s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_id == AV_CODEC_ID_DNXHD) { + // clip-wrapping requires 0x0D per ST2019-4:2009 or 0x06 per previous version ST2019-4:2008 + // we choose to use 0x06 instead 0x0D to be compatible with AVID systems + // and produce mxf files with the most relevant flavour for opatom + sc->track_essence_element_key[14] = 0x06; + } PRINT_KEY(s, "track essence element key", sc->track_essence_element_key); if (!present[sc->index]) diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index b818f26c36..e34cf2559e 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -e558e50a94d88762e07ab8149aced7b9 *tests/data/lavf/lavf.mxf_opatom +aab6397829bd90f0c77a3f9fde53bb9c *tests/data/lavf/lavf.mxf_opatom 4717625 tests/data/lavf/lavf.mxf_opatom tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a From db901276c0ae4799a0d2c8f81f09497dd66b4ed7 Mon Sep 17 00:00:00 2001 From: Zhang yuankun Date: Mon, 12 Apr 2021 09:47:24 +0800 Subject: [PATCH 640/894] avcodec/vaapi_encode_vp9: fix > 4k encode fail issue This patch will fix following command: ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -i input.264 \ -vf 'scale_vaapi=w=7680:h=4096' -c:v vp9_vaapi output.ivf Max width of a vp9 tile is 4096. If the source frame > 4096, we need split to multiple tiles. Reviewed-by: Limin Wang Signed-off-by: Zhang yuankun Signed-off-by: Haihao Xiang --- libavcodec/vaapi_encode_vp9.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index b3f45fb8fe..be706e3bd6 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -31,6 +31,7 @@ #define VP9_MAX_QUANT 255 +#define VP9_MAX_TILE_WIDTH 4096 typedef struct VAAPIEncodeVP9Picture { int slot; @@ -82,10 +83,17 @@ static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx, VAAPIEncodeVP9Picture *hpic = pic->priv_data; VAEncPictureParameterBufferVP9 *vpic = pic->codec_picture_params; int i; + int num_tile_columns; vpic->reconstructed_frame = pic->recon_surface; vpic->coded_buf = pic->output_buffer; + // Maximum width of a tile in units of superblocks is MAX_TILE_WIDTH_B64(64) + // So the number of tile columns is related to the width of the picture. + // We set the minimum possible number for num_tile_columns as default value. + num_tile_columns = (vpic->frame_width_src + VP9_MAX_TILE_WIDTH - 1) / VP9_MAX_TILE_WIDTH; + vpic->log2_tile_columns = num_tile_columns == 1 ? 0 : av_log2(num_tile_columns - 1) + 1; + switch (pic->type) { case PICTURE_TYPE_IDR: av_assert0(pic->nb_refs == 0); From c2a538926933f4339f7789c47b2e21123be8a37c Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 25 Dec 2021 11:48:58 +0800 Subject: [PATCH 641/894] avcodec/qsvenc_hevc: use AV_OPT_TYPE_BOOL for aud option Signed-off-by: Limin Wang Signed-off-by: Haihao Xiang --- libavcodec/qsvenc_hevc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 5847ea21f7..08aba3011d 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -250,7 +250,7 @@ static const AVOption options[] = { { "tile_cols", "Number of columns for tiled encoding", OFFSET(qsv.tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, { "tile_rows", "Number of rows for tiled encoding", OFFSET(qsv.tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, - { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { NULL }, }; From 617452ce2c7857bdac40d4b33724e414d2712e7c Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 25 Dec 2021 11:48:59 +0800 Subject: [PATCH 642/894] avcodec/qsvenc_h264: use AV_OPT_TYPE_BOOL for aud, a53cc, cavlc, look_ahead, pic_timing_sei options Signed-off-by: Limin Wang Signed-off-by: Haihao Xiang --- libavcodec/qsvenc_h264.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 80fe3cc280..9f127607b7 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -103,17 +103,17 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) static const AVOption options[] = { QSV_COMMON_OPTS - { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #if QSV_HAVE_VCM - { "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #endif { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, - { "pic_timing_sei", "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { "pic_timing_sei", "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, { "single_sei_nal_unit", "Put all the SEI messages into one NALU", OFFSET(qsv.single_sei_nal_unit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, { "max_dec_frame_buffering", "Maximum number of frames buffered in the DPB", OFFSET(qsv.max_dec_frame_buffering), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, #if QSV_HAVE_LA - { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "look_ahead_depth", "Depth of look ahead in number frames", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE }, #endif #if QSV_HAVE_LA_DS @@ -139,9 +139,9 @@ static const AVOption options[] = { { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "high" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, - { "a53cc" , "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, VE}, + { "a53cc" , "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE}, - { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, #if QSV_HAVE_MF { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode), AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, MFX_MF_DEFAULT, MFX_MF_AUTO, VE, "mfmode"}, From 7dfc3cc713ea0dbe7aeedcc2a272a5382a36dbcd Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 25 Dec 2021 22:21:03 +0800 Subject: [PATCH 643/894] avcodec/libx26[45]: add udu_sei option to import user data unregistered SEIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of user data unregistered SEIs are privated data which defined by user/ encoder. currently, the user data unregistered SEIs found in input are forwarded as side-data to encoders directly, it'll cause the reencoded output including some useless UDU SEIs. I prefer to add one option to enable/disable it and default is off after I saw the patch by Andreas Rheinhardt: https://patchwork.ffmpeg.org/project/ffmpeg/patch/AM7PR03MB66607C2DB65E1AD49D975CF18F7B9@AM7PR03MB6660.eurprd03.prod.outlook.com/ How to test by cli: ffmpeg -y -f lavfi -i testsrc -c:v libx264 -frames:v 1 a.ts ffmpeg -y -i a.ts -c:v libx264 -udu_sei 1 b.ts ffmpeg -y -i a.ts -c:v libx264 -udu_sei 0 c.ts # check the user data unregistered SEIs, you'll see two UDU SEIs for b.ts. # and mediainfo will show with wrong encoding setting info ffmpeg -i b.ts -vf showinfo -f null - ffmpeg -i c.ts -vf showinfo -f null - This fixes tickets #9500 and #9557. Reviewed-by: "zhilizhao(赵志立)" Signed-off-by: Limin Wang --- doc/encoders.texi | 6 ++++++ libavcodec/libx264.c | 5 ++++- libavcodec/libx265.c | 4 ++++ libavcodec/version.h | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 8a7589c245..e3b61de5a1 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -2660,6 +2660,9 @@ ffmpeg -i foo.mpg -c:v libx264 -x264opts keyint=123:min-keyint=20 -an out.mkv Import closed captions (which must be ATSC compatible format) into output. Only the mpeg2 and h264 decoders provide these. Default is 1 (on). +@item udu_sei @var{boolean} +Import user data unregistered SEI if available into output. Default is 0 (off). + @item x264-params (N.A.) Override the x264 configuration using a :-separated list of key=value parameters. @@ -2741,6 +2744,9 @@ Quantizer curve compression factor Normally, when forcing a I-frame type, the encoder can select any type of I-frame. This option forces it to choose an IDR-frame. +@item udu_sei @var{boolean} +Import user data unregistered SEI if available into output. Default is 0 (off). + @item x265-params Set x265 options using a list of @var{key}=@var{value} couples separated by ":". See @command{x265 --help} for a list of options. diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 2b680abf21..9836818b99 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -104,6 +104,7 @@ typedef struct X264Context { int chroma_offset; int scenechange_threshold; int noise_reduction; + int udu_sei; AVDictionary *x264_params; @@ -464,6 +465,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, } } + if (x4->udu_sei) { for (int j = 0; j < frame->nb_side_data; j++) { AVFrameSideData *side_data = frame->side_data[j]; void *tmp; @@ -487,6 +489,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, sei_payload->payload_type = SEI_TYPE_USER_DATA_UNREGISTERED; sei->num_payloads++; } + } } do { @@ -1168,7 +1171,7 @@ static const AVOption options[] = { { "chromaoffset", "QP difference between chroma and luma", OFFSET(chroma_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, VE }, { "sc_threshold", "Scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, { "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, - + { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, { NULL }, }; diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 7dd70a3450..47d0103a40 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -54,6 +54,7 @@ typedef struct libx265Context { void *sei_data; int sei_data_size; + int udu_sei; /** * If the encoder does not support ROI then warn the first time we @@ -543,6 +544,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, memcpy(x265pic.userData, &pic->reordered_opaque, sizeof(pic->reordered_opaque)); } + if (ctx->udu_sei) { for (i = 0; i < pic->nb_side_data; i++) { AVFrameSideData *side_data = pic->side_data[i]; void *tmp; @@ -568,6 +570,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, sei_payload->payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; sei->numPayloads++; } + } } ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, @@ -708,6 +711,7 @@ static const AVOption options[] = { { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "profile", "set the x265 profile", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, { NULL } }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 580b099b36..45c6d13ae7 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 59 #define LIBAVCODEC_VERSION_MINOR 15 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 63d5b6f9350701a9d1af7d8d532f10d6f6b69039 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 25 Dec 2021 22:28:30 +0800 Subject: [PATCH 644/894] avcodec/libx26[45]: reindent after last commit Signed-off-by: Limin Wang --- libavcodec/libx264.c | 44 ++++++++++++++++++++++---------------------- libavcodec/libx265.c | 44 ++++++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 9836818b99..c5e0231b12 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -466,29 +466,29 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, } if (x4->udu_sei) { - for (int j = 0; j < frame->nb_side_data; j++) { - AVFrameSideData *side_data = frame->side_data[j]; - void *tmp; - x264_sei_payload_t *sei_payload; - if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) - continue; - tmp = av_fast_realloc(sei->payloads, &sei_data_size, (sei->num_payloads + 1) * sizeof(*sei_payload)); - if (!tmp) { - free_picture(ctx); - return AVERROR(ENOMEM); + for (int j = 0; j < frame->nb_side_data; j++) { + AVFrameSideData *side_data = frame->side_data[j]; + void *tmp; + x264_sei_payload_t *sei_payload; + if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) + continue; + tmp = av_fast_realloc(sei->payloads, &sei_data_size, (sei->num_payloads + 1) * sizeof(*sei_payload)); + if (!tmp) { + free_picture(ctx); + return AVERROR(ENOMEM); + } + sei->payloads = tmp; + sei->sei_free = av_free; + sei_payload = &sei->payloads[sei->num_payloads]; + sei_payload->payload = av_memdup(side_data->data, side_data->size); + if (!sei_payload->payload) { + free_picture(ctx); + return AVERROR(ENOMEM); + } + sei_payload->payload_size = side_data->size; + sei_payload->payload_type = SEI_TYPE_USER_DATA_UNREGISTERED; + sei->num_payloads++; } - sei->payloads = tmp; - sei->sei_free = av_free; - sei_payload = &sei->payloads[sei->num_payloads]; - sei_payload->payload = av_memdup(side_data->data, side_data->size); - if (!sei_payload->payload) { - free_picture(ctx); - return AVERROR(ENOMEM); - } - sei_payload->payload_size = side_data->size; - sei_payload->payload_type = SEI_TYPE_USER_DATA_UNREGISTERED; - sei->num_payloads++; - } } } diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 47d0103a40..851f099343 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -545,31 +545,31 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } if (ctx->udu_sei) { - for (i = 0; i < pic->nb_side_data; i++) { - AVFrameSideData *side_data = pic->side_data[i]; - void *tmp; - x265_sei_payload *sei_payload; + for (i = 0; i < pic->nb_side_data; i++) { + AVFrameSideData *side_data = pic->side_data[i]; + void *tmp; + x265_sei_payload *sei_payload; - if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) - continue; + if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) + continue; - tmp = av_fast_realloc(ctx->sei_data, - &ctx->sei_data_size, - (sei->numPayloads + 1) * sizeof(*sei_payload)); - if (!tmp) { - av_freep(&x265pic.userData); - av_freep(&x265pic.quantOffsets); - return AVERROR(ENOMEM); + tmp = av_fast_realloc(ctx->sei_data, + &ctx->sei_data_size, + (sei->numPayloads + 1) * sizeof(*sei_payload)); + if (!tmp) { + av_freep(&x265pic.userData); + av_freep(&x265pic.quantOffsets); + return AVERROR(ENOMEM); + } + ctx->sei_data = tmp; + sei->payloads = ctx->sei_data; + sei_payload = &sei->payloads[sei->numPayloads]; + sei_payload->payload = side_data->data; + sei_payload->payloadSize = side_data->size; + /* Equal to libx265 USER_DATA_UNREGISTERED */ + sei_payload->payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; + sei->numPayloads++; } - ctx->sei_data = tmp; - sei->payloads = ctx->sei_data; - sei_payload = &sei->payloads[sei->numPayloads]; - sei_payload->payload = side_data->data; - sei_payload->payloadSize = side_data->size; - /* Equal to libx265 USER_DATA_UNREGISTERED */ - sei_payload->payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; - sei->numPayloads++; - } } } From 30322ebe3c55d0fb18bea4ae04d0fcaf1f97d27f Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 14 Dec 2021 02:12:15 +0000 Subject: [PATCH 645/894] avcodec/v4l2_m2m_dec: dequeue frame if input isn't ready The V4L2M2M API operates asynchronously, so multiple packets can be enqueued before getting a batch of frames back. Since it was only possible to receive a frame by submitting another packet, there wasn't a way to drain those excess output frames from when avcodec_receive_frame() returned AVERROR(EAGAIN). Reviewed-by: Andriy Gelman Signed-off-by: Cameron Gutman --- libavcodec/v4l2_m2m_dec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 224eb3d5e7..b0c3d30ac8 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -142,8 +142,12 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (!s->buf_pkt.size) { ret = ff_decode_get_packet(avctx, &s->buf_pkt); - if (ret < 0 && ret != AVERROR_EOF) - return ret; + if (ret < 0) { + if (ret == AVERROR(EAGAIN)) + return ff_v4l2_context_dequeue_frame(capture, frame, 0); + else if (ret != AVERROR_EOF) + return ret; + } } if (s->draining) From 12f21849e550280c7e577e9958ead9aa42a29584 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 30 Dec 2021 17:10:30 +0530 Subject: [PATCH 646/894] doc/demuxers: add entry for aac --- doc/demuxers.texi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index cab8a7072c..593ff34c86 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -25,6 +25,13 @@ Audible Format 2, 3, and 4 demuxer. This demuxer is used to demux Audible Format 2, 3, and 4 (.aa) files. +@section aac + +Raw Audio Data Transport Stream AAC demuxer. + +This demuxer is used to demux an ADTS input containing a single AAC stream +alongwith any ID3v1/2 or APE tags in it. + @section apng Animated Portable Network Graphics demuxer. From b32b32ba89b564e33c6ee0d7a17b80b5e56b6b73 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 13 Dec 2021 21:56:05 +0100 Subject: [PATCH 647/894] lavc/mediacodecdec: set codec profile and level from extradata for H264+HEVC This value is later passed to MediaCodec and checked at decoder init. Notably decoding of 10-bit streams before this commit would "work" without returning errors but only return garbage output (on most Android devices). --- libavcodec/mediacodecdec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 1cebb3d76d..04d5026e68 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -155,6 +155,9 @@ static int h264_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) uint8_t *data = NULL; int data_size = 0; + avctx->profile = ff_h264_get_profile(sps); + avctx->level = sps->level_idc; + if ((ret = h2645_ps_to_nalu(sps->data, sps->data_size, &data, &data_size)) < 0) { goto done; } @@ -236,6 +239,9 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) uint8_t *data; int data_size; + avctx->profile = sps->ptl.general_ptl.profile_idc; + avctx->level = sps->ptl.general_ptl.level_idc; + if ((ret = h2645_ps_to_nalu(vps->data, vps->data_size, &vps_data, &vps_data_size)) < 0 || (ret = h2645_ps_to_nalu(sps->data, sps->data_size, &sps_data, &sps_data_size)) < 0 || (ret = h2645_ps_to_nalu(pps->data, pps->data_size, &pps_data, &pps_data_size)) < 0) { From 65197e9c98f46a79dd02c993cfcb0e70f65878cf Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 13 Dec 2021 21:55:41 +0100 Subject: [PATCH 648/894] lavf/tls_mbedtls: fix handling of tls_verify=0 If ca_file was set, setting tls_verify=0 would not actually disable verification. --- libavformat/tls_mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/tls_mbedtls.c b/libavformat/tls_mbedtls.c index aadf17760d..5754d0d018 100644 --- a/libavformat/tls_mbedtls.c +++ b/libavformat/tls_mbedtls.c @@ -223,7 +223,7 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op } mbedtls_ssl_conf_authmode(&tls_ctx->ssl_config, - shr->ca_file ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE); + shr->verify ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&tls_ctx->ssl_config, mbedtls_ctr_drbg_random, &tls_ctx->ctr_drbg_context); mbedtls_ssl_conf_ca_chain(&tls_ctx->ssl_config, &tls_ctx->ca_cert, NULL); From afdbc940c6011b64c1856f88d2b0609369f87406 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 25 Dec 2021 20:14:48 +0100 Subject: [PATCH 649/894] avcodec/tiff: Remove messing with jpeg context The whole concept is just not correct, also as it seems not to be needed at all, all dng files i have decode without this. Fixes: various crashes Fixes: 42937/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-4625073334517760 Fixes: 42938/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-4643368217477120 Fixes: 42939/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-4925325908246528 Fixes: 42940/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-4925378806808576 Fixes: 42941/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-6202009265504256 Fixes: 42944/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-6076860998483968 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 60773d59ed..fd85d104dc 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -721,20 +721,6 @@ static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) -{ - TiffContext *s = avctx->priv_data; - int ret = ff_set_dimensions(s->avctx_mjpeg, s->width, s->height); - - if (ret < 0) - return ret; - - s->jpgframe->width = s->width; - s->jpgframe->height = s->height; - - return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); -} - static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -856,7 +842,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); return AVERROR_PATCHWELCOME; } - if ((ret = dng_decode_strip(s->avctx, p)) < 0) + if ((ret = dng_decode_jpeg(s->avctx, p, s->stripsize, 0, 0, s->width, s->height)) < 0) return ret; return 0; } @@ -972,13 +958,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; - int ret = ff_set_dimensions(s->avctx_mjpeg, s->tile_width, s->tile_length); - - if (ret < 0) - return ret; - - s->jpgframe->width = s->tile_width; - s->jpgframe->height = s->tile_length; + int ret; has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); From 68f8292aa96d99b733ca7d2e56b584b00263db84 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Dec 2021 20:17:14 +0100 Subject: [PATCH 650/894] avcodec/targa: Check input size for uncompressed TGA before allocation Fixes: Timeout Fixes: 42667/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TARGA_fuzzer-5619236075077632 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/targa.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/targa.c b/libavcodec/targa.c index 221fcc956d..b0048621d3 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -117,6 +117,7 @@ static int decode_frame(AVCodecContext *avctx, int idlen, pal, compr, y, w, h, bpp, flags, ret; int first_clr, colors, csize; int interleave; + size_t img_size; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -180,6 +181,15 @@ static int decode_frame(AVCodecContext *avctx, return avpkt->size; } + if (!(compr & TGA_RLE)) { + img_size = w * ((bpp + 1) >> 3); + if (bytestream2_get_bytes_left(&s->gb) < img_size * h) { + av_log(avctx, AV_LOG_ERROR, + "Not enough data available for image\n"); + return AVERROR_INVALIDDATA; + } + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; @@ -251,7 +261,6 @@ static int decode_frame(AVCodecContext *avctx, if (res < 0) return res; } else { - size_t img_size = w * ((bpp + 1) >> 3); uint8_t *line; if (bytestream2_get_bytes_left(&s->gb) < img_size * h) { av_log(avctx, AV_LOG_ERROR, From c217ca7718c8e24905d7ba9ede719ae040899476 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Dec 2021 20:36:16 +0100 Subject: [PATCH 651/894] avformat/flvdec: timestamps cannot use the full int64 range We do not support this as we multiply by 1000 Fixes: signed integer overflow: -45318575073853696 * 1000 cannot be represented in type 'long' Fixes: 42804/clusterfuzz-testcase-minimized-ffmpeg_dem_LIVE_FLV_fuzzer-4630325425209344 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/flvdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 44a7e5f93c..b9e36b3ff1 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -461,6 +461,8 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t m d = av_int2double(avio_rb64(ioc)); if (isnan(d) || d < INT64_MIN || d > INT64_MAX) goto invalid; + if (current_array == × && (d <= INT64_MIN / 1000 || d >= INT64_MAX / 1000)) + goto invalid; current_array[0][i] = d; } if (times && filepositions) { From 7cee3b37187dbf61dbebff023f07ceedfc0129bb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Dec 2021 20:39:14 +0100 Subject: [PATCH 652/894] avcodec/apedec: fix integer overflow in 8bit samples Fixes: signed integer overflow: 2147483542 + 128 cannot be represented in type 'int' Fixes: 42812/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APE_fuzzer-6344057861832704 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/apedec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 35a2e617e6..b932263012 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -1587,7 +1587,7 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data, for (ch = 0; ch < s->channels; ch++) { sample8 = (uint8_t *)frame->data[ch]; for (i = 0; i < blockstodecode; i++) - *sample8++ = (s->decoded[ch][i] + 0x80) & 0xff; + *sample8++ = (s->decoded[ch][i] + 0x80U) & 0xff; } break; case 16: From d590e211a28cecd04559ab9a6a223a87fa974ee3 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 22 Dec 2021 22:36:17 +0800 Subject: [PATCH 653/894] avformat: add bitpacked demuxer Allows user can playback bitpacked pixel format directly: ffplay -video_size 1280x720 -pixel_format yuv422p10 test.bitpacked ffplay -f bitpacked -video_size 1280x720 -pixel_format uyvy422 test.yuv Signed-off-by: Limin Wang --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/rawvideodec.c | 55 ++++++++++++++++++++++++++++++++++++--- libavformat/version.h | 2 +- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 2b5caf9d33..65fb789aa3 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -138,6 +138,7 @@ OBJS-$(CONFIG_BINKA_DEMUXER) += binka.o OBJS-$(CONFIG_BINTEXT_DEMUXER) += bintext.o sauce.o OBJS-$(CONFIG_BIT_DEMUXER) += bit.o OBJS-$(CONFIG_BIT_MUXER) += bit.o +OBJS-$(CONFIG_BITPACKED_DEMUXER) += rawvideodec.o OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o OBJS-$(CONFIG_BFSTM_DEMUXER) += brstm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 1054ac9667..a100639773 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -96,6 +96,7 @@ extern const AVInputFormat ff_bink_demuxer; extern const AVInputFormat ff_binka_demuxer; extern const AVInputFormat ff_bit_demuxer; extern const AVOutputFormat ff_bit_muxer; +extern const AVInputFormat ff_bitpacked_demuxer; extern const AVInputFormat ff_bmv_demuxer; extern const AVInputFormat ff_bfstm_demuxer; extern const AVInputFormat ff_brstm_demuxer; diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 5049a29b9c..710724c2d1 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -59,10 +59,38 @@ static int rawvideo_read_header(AVFormatContext *ctx) st->codecpar->width = s->width; st->codecpar->height = s->height; + + if (ctx->iformat->raw_codec_id == AV_CODEC_ID_BITPACKED) { + unsigned int pgroup; /* size of the pixel group in bytes */ + unsigned int xinc; + const AVPixFmtDescriptor *desc; + int tag; + + desc = av_pix_fmt_desc_get(pix_fmt); + st->codecpar->bits_per_coded_sample = av_get_bits_per_pixel(desc); + if (pix_fmt == AV_PIX_FMT_YUV422P10) { + tag = MKTAG('U', 'Y', 'V', 'Y'); + pgroup = 5; + xinc = 2; + } else if (pix_fmt == AV_PIX_FMT_UYVY422) { + tag = MKTAG('U', 'Y', 'V', 'Y'); + pgroup = 4; + xinc = 2; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + av_log(ctx, AV_LOG_ERROR, "unsupported format: %s for bitpacked.\n", + s->pixel_format); + return AVERROR(EINVAL); + } + st->codecpar->codec_tag = tag; + packet_size = s->width * s->height * pgroup / xinc; + } else { + packet_size = av_image_get_buffer_size(pix_fmt, s->width, s->height, 1); + if (packet_size < 0) + return packet_size; + } + st->codecpar->format = pix_fmt; - packet_size = av_image_get_buffer_size(st->codecpar->format, s->width, s->height, 1); - if (packet_size < 0) - return packet_size; ctx->packet_size = packet_size; st->codecpar->bit_rate = av_rescale_q(ctx->packet_size, (AVRational){8,1}, st->time_base); @@ -111,3 +139,24 @@ const AVInputFormat ff_rawvideo_demuxer = { .raw_codec_id = AV_CODEC_ID_RAWVIDEO, .priv_class = &rawvideo_demuxer_class, }; + +static const AVClass bitpacked_demuxer_class = { + .class_name = "bitpacked demuxer", + .item_name = av_default_item_name, + .option = rawvideo_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +#if CONFIG_BITPACKED_DEMUXER +const AVInputFormat ff_bitpacked_demuxer = { + .name = "bitpacked", + .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .priv_data_size = sizeof(RawVideoDemuxerContext), + .read_header = rawvideo_read_header, + .read_packet = rawvideo_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "bitpacked", + .raw_codec_id = AV_CODEC_ID_BITPACKED, + .priv_class = &bitpacked_demuxer_class, +}; +#endif // CONFIG_BITPACKED_DEMUXER diff --git a/libavformat/version.h b/libavformat/version.h index 379a68cc7c..9b90bbf156 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 10 +#define LIBAVFORMAT_VERSION_MINOR 11 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 73f6cce936130abde06ec3a39d0a4cdabfef01e4 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Sun, 26 Dec 2021 16:47:57 -0800 Subject: [PATCH 654/894] avformat/imf: Demuxer Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- configure | 3 +- doc/demuxers.texi | 6 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/imf.h | 207 +++++++++ libavformat/imf_cpl.c | 841 ++++++++++++++++++++++++++++++++++++ libavformat/imfdec.c | 899 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 8 files changed, 1958 insertions(+), 2 deletions(-) create mode 100644 libavformat/imf.h create mode 100644 libavformat/imf_cpl.c create mode 100644 libavformat/imfdec.c diff --git a/configure b/configure index 23ef2abc9b..07fb7925d8 100755 --- a/configure +++ b/configure @@ -298,7 +298,7 @@ External library support: --enable-libxvid enable Xvid encoding via xvidcore, native MPEG-4/Xvid encoder exists [no] --enable-libxml2 enable XML parsing using the C library libxml2, needed - for dash demuxing support [no] + for dash and imf demuxing support [no] --enable-libzimg enable z.lib, needed for zscale filter [no] --enable-libzmq enable message passing via libzmq [no] --enable-libzvbi enable teletext support via libzvbi [no] @@ -3415,6 +3415,7 @@ hls_muxer_select="mpegts_muxer" hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" +imf_demuxer_deps="libxml2" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 593ff34c86..b474a24278 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -274,6 +274,12 @@ which streams to actually receive. Each stream mirrors the @code{id} and @code{bandwidth} properties from the @code{} as metadata keys named "id" and "variant_bitrate" respectively. +@section imf + +Interoperable Master Format demuxer. + +This demuxer presents audio and video streams found in an IMF Composition. + @section flv, live_flv, kux Adobe Flash Video Format demuxer. diff --git a/libavformat/Makefile b/libavformat/Makefile index 65fb789aa3..74b1c56351 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -286,6 +286,7 @@ OBJS-$(CONFIG_IMAGE_WEBP_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XPM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XWD_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMF_DEMUXER) += imfdec.o imf_cpl.o OBJS-$(CONFIG_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o OBJS-$(CONFIG_IPU_DEMUXER) += ipudec.o rawdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index a100639773..d066a7745b 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -213,6 +213,7 @@ extern const AVInputFormat ff_image2pipe_demuxer; extern const AVOutputFormat ff_image2pipe_muxer; extern const AVInputFormat ff_image2_alias_pix_demuxer; extern const AVInputFormat ff_image2_brender_pix_demuxer; +extern const AVInputFormat ff_imf_demuxer; extern const AVInputFormat ff_ingenient_demuxer; extern const AVInputFormat ff_ipmovie_demuxer; extern const AVOutputFormat ff_ipod_muxer; diff --git a/libavformat/imf.h b/libavformat/imf.h new file mode 100644 index 0000000000..62c4468ce9 --- /dev/null +++ b/libavformat/imf.h @@ -0,0 +1,207 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * + * Copyright (c) Sandflow Consulting LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Public header file for the processing of Interoperable Master Format (IMF) + * packages. + * + * @author Pierre-Anthony Lemieux + * @author Valentin Noel + * @file + * @ingroup lavu_imf + */ + +#ifndef AVFORMAT_IMF_H +#define AVFORMAT_IMF_H + +#include "avformat.h" +#include "libavformat/avio.h" +#include "libavutil/rational.h" +#include + +#define FF_IMF_UUID_FORMAT \ + "urn:uuid:%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-" \ + "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" + +/** + * UUID as defined in IETF RFC 422 + */ +typedef uint8_t FFIMFUUID[16]; + +/** + * IMF Composition Playlist Base Resource + */ +typedef struct FFIMFBaseResource { + AVRational edit_rate; /**< BaseResourceType/EditRate */ + uint32_t entry_point; /**< BaseResourceType/EntryPoint */ + uint32_t duration; /**< BaseResourceType/Duration */ + uint32_t repeat_count; /**< BaseResourceType/RepeatCount */ +} FFIMFBaseResource; + +/** + * IMF Composition Playlist Track File Resource + */ +typedef struct FFIMFTrackFileResource { + FFIMFBaseResource base; + FFIMFUUID track_file_uuid; /**< TrackFileResourceType/TrackFileId */ +} FFIMFTrackFileResource; + +/** + * IMF Marker + */ +typedef struct FFIMFMarker { + xmlChar *label_utf8; /**< Marker/Label */ + xmlChar *scope_utf8; /**< Marker/Label/\@scope */ + uint32_t offset; /**< Marker/Offset */ +} FFIMFMarker; + +/** + * IMF Composition Playlist Marker Resource + */ +typedef struct FFIMFMarkerResource { + FFIMFBaseResource base; + uint32_t marker_count; /**< Number of Marker elements */ + FFIMFMarker *markers; /**< Marker elements */ +} FFIMFMarkerResource; + +/** + * IMF Composition Playlist Virtual Track + */ +typedef struct FFIMFBaseVirtualTrack { + FFIMFUUID id_uuid; /**< TrackId associated with the Virtual Track */ +} FFIMFBaseVirtualTrack; + +/** + * IMF Composition Playlist Virtual Track that consists of Track File Resources + */ +typedef struct FFIMFTrackFileVirtualTrack { + FFIMFBaseVirtualTrack base; + uint32_t resource_count; /**< Number of Resource elements present in the Virtual Track */ + FFIMFTrackFileResource *resources; /**< Resource elements of the Virtual Track */ + unsigned int resources_alloc_sz; /**< Size of the resources buffer */ +} FFIMFTrackFileVirtualTrack; + +/** + * IMF Composition Playlist Virtual Track that consists of Marker Resources + */ +typedef struct FFIMFMarkerVirtualTrack { + FFIMFBaseVirtualTrack base; + uint32_t resource_count; /**< Number of Resource elements present in the Virtual Track */ + FFIMFMarkerResource *resources; /**< Resource elements of the Virtual Track */ +} FFIMFMarkerVirtualTrack; + +/** + * IMF Composition Playlist + */ +typedef struct FFIMFCPL { + FFIMFUUID id_uuid; /**< CompositionPlaylist/Id element */ + xmlChar *content_title_utf8; /**< CompositionPlaylist/ContentTitle element */ + AVRational edit_rate; /**< CompositionPlaylist/EditRate element */ + FFIMFMarkerVirtualTrack *main_markers_track; /**< Main Marker Virtual Track */ + FFIMFTrackFileVirtualTrack *main_image_2d_track; /**< Main Image Virtual Track */ + uint32_t main_audio_track_count; /**< Number of Main Audio Virtual Tracks */ + FFIMFTrackFileVirtualTrack *main_audio_tracks; /**< Main Audio Virtual Tracks */ +} FFIMFCPL; + +/** + * Parse an IMF CompositionPlaylist element into the FFIMFCPL data structure. + * @param[in] doc An XML document from which the CPL is read. + * @param[out] cpl Pointer to a memory area (allocated by the client), where the + * function writes a pointer to the newly constructed FFIMFCPL structure (or + * NULL if the CPL could not be parsed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + * @return A non-zero value in case of an error. + */ +int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl); + +/** + * Parse an IMF Composition Playlist document into the FFIMFCPL data structure. + * @param[in] in The context from which the CPL is read. + * @param[out] cpl Pointer to a memory area (allocated by the client), where the + * function writes a pointer to the newly constructed FFIMFCPL structure (or + * NULL if the CPL could not be parsed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + * @return A non-zero value in case of an error. + */ +int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl); + +/** + * Allocates and initializes an FFIMFCPL data structure. + * @return A pointer to the newly constructed FFIMFCPL structure (or NULL if the + * structure could not be constructed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + */ +FFIMFCPL *ff_imf_cpl_alloc(void); + +/** + * Deletes an FFIMFCPL data structure previously instantiated with ff_imf_cpl_alloc(). + * @param[in] cpl The FFIMFCPL structure to delete. + */ +void ff_imf_cpl_free(FFIMFCPL *cpl); + +/** + * Reads an unsigned 32-bit integer from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number); + +/** + * Reads an AVRational from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational); + +/** + * Reads a UUID from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_imf_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]); + +/** + * Returns the first child element with the specified local name + * @return A pointer to the child element, or NULL if no such child element exists. + */ +xmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8); + +#endif diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c new file mode 100644 index 0000000000..7055b49ae8 --- /dev/null +++ b/libavformat/imf_cpl.c @@ -0,0 +1,841 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * + * Copyright (c) Sandflow Consulting LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Implements IMP CPL processing + * + * @author Pierre-Anthony Lemieux + * @file + * @ingroup lavu_imf + */ + +#include "imf.h" +#include "libavformat/mxf.h" +#include "libavutil/bprint.h" +#include "libavutil/error.h" +#include + +xmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8) +{ + xmlNodePtr cur_element; + + cur_element = xmlFirstElementChild(parent); + while (cur_element) { + if (xmlStrcmp(cur_element->name, name_utf8) == 0) + return cur_element; + + cur_element = xmlNextElementSibling(cur_element); + } + return NULL; +} + +int ff_imf_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]) +{ + xmlChar *element_text = NULL; + int scanf_ret; + int ret = 0; + + element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + scanf_ret = sscanf(element_text, + FF_IMF_UUID_FORMAT, + &uuid[0], + &uuid[1], + &uuid[2], + &uuid[3], + &uuid[4], + &uuid[5], + &uuid[6], + &uuid[7], + &uuid[8], + &uuid[9], + &uuid[10], + &uuid[11], + &uuid[12], + &uuid[13], + &uuid[14], + &uuid[15]); + if (scanf_ret != 16) { + av_log(NULL, AV_LOG_ERROR, "Invalid UUID\n"); + ret = AVERROR_INVALIDDATA; + } + xmlFree(element_text); + + return ret; +} + +int ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational) +{ + xmlChar *element_text = NULL; + int ret = 0; + + element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + if (sscanf(element_text, "%i %i", &rational->num, &rational->den) != 2) { + av_log(NULL, AV_LOG_ERROR, "Invalid rational number\n"); + ret = AVERROR_INVALIDDATA; + } + xmlFree(element_text); + + return ret; +} + +int ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number) +{ + xmlChar *element_text = NULL; + int ret = 0; + + element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + if (sscanf(element_text, "%" PRIu32, number) != 1) { + av_log(NULL, AV_LOG_ERROR, "Invalid unsigned 32-bit integer"); + ret = AVERROR_INVALIDDATA; + } + xmlFree(element_text); + + return ret; +} + +static void imf_base_virtual_track_init(FFIMFBaseVirtualTrack *track) +{ + memset(track->id_uuid, 0, sizeof(track->id_uuid)); +} + +static void imf_marker_virtual_track_init(FFIMFMarkerVirtualTrack *track) +{ + imf_base_virtual_track_init((FFIMFBaseVirtualTrack *)track); + track->resource_count = 0; + track->resources = NULL; +} + +static void imf_trackfile_virtual_track_init(FFIMFTrackFileVirtualTrack *track) +{ + imf_base_virtual_track_init((FFIMFBaseVirtualTrack *)track); + track->resource_count = 0; + track->resources_alloc_sz = 0; + track->resources = NULL; +} + +static void imf_base_resource_init(FFIMFBaseResource *rsrc) +{ + rsrc->duration = 0; + rsrc->edit_rate = av_make_q(0, 1); + rsrc->entry_point = 0; + rsrc->repeat_count = 1; +} + +static void imf_marker_resource_init(FFIMFMarkerResource *rsrc) +{ + imf_base_resource_init((FFIMFBaseResource *)rsrc); + rsrc->marker_count = 0; + rsrc->markers = NULL; +} + +static void imf_marker_init(FFIMFMarker *marker) +{ + marker->label_utf8 = NULL; + marker->offset = 0; + marker->scope_utf8 = NULL; +} + +static void imf_trackfile_resource_init(FFIMFTrackFileResource *rsrc) +{ + imf_base_resource_init((FFIMFBaseResource *)rsrc); + memset(rsrc->track_file_uuid, 0, sizeof(rsrc->track_file_uuid)); +} + +static int fill_content_title(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "ContentTitle"))) { + av_log(NULL, AV_LOG_ERROR, "ContentTitle element not found in the IMF CPL\n"); + return AVERROR_INVALIDDATA; + } + cpl->content_title_utf8 = xmlNodeListGetString(cpl_element->doc, + element->xmlChildrenNode, + 1); + + return 0; +} + +static int fill_edit_rate(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "EditRate"))) { + av_log(NULL, AV_LOG_ERROR, "EditRate element not found in the IMF CPL\n"); + return AVERROR_INVALIDDATA; + } + + return ff_imf_xml_read_rational(element, &cpl->edit_rate); +} + +static int fill_id(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "Id"))) { + av_log(NULL, AV_LOG_ERROR, "Id element not found in the IMF CPL\n"); + return AVERROR_INVALIDDATA; + } + + return ff_imf_xml_read_uuid(element, cpl->id_uuid); +} + +static int fill_marker(xmlNodePtr marker_elem, FFIMFMarker *marker) +{ + xmlNodePtr element = NULL; + int ret = 0; + + /* read Offset */ + if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Offset"))) { + av_log(NULL, AV_LOG_ERROR, "Offset element not found in a Marker\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uint32(element, &marker->offset))) + return ret; + + /* read Label and Scope */ + if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Label"))) { + av_log(NULL, AV_LOG_ERROR, "Label element not found in a Marker\n"); + return AVERROR_INVALIDDATA; + } + if (!(marker->label_utf8 = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1))) { + av_log(NULL, AV_LOG_ERROR, "Empty Label element found in a Marker\n"); + return AVERROR_INVALIDDATA; + } + if (!(marker->scope_utf8 = xmlGetNoNsProp(element, "scope"))) { + marker->scope_utf8 + = xmlCharStrdup("http://www.smpte-ra.org/schemas/2067-3/2013#standard-markers"); + if (!marker->scope_utf8) { + xmlFree(marker->label_utf8); + return AVERROR(ENOMEM); + } + } + + return ret; +} + +static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resource, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + int ret = 0; + + /* read EditRate */ + if (!(element = ff_imf_xml_get_child_element_by_name(resource_elem, "EditRate"))) { + resource->edit_rate = cpl->edit_rate; + } else if ((ret = ff_imf_xml_read_rational(element, &resource->edit_rate))) { + av_log(NULL, AV_LOG_ERROR, "Invalid EditRate element found in a Resource\n"); + return ret; + } + + /* read EntryPoint */ + if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "EntryPoint"))) { + if ((ret = ff_imf_xml_read_uint32(element, &resource->entry_point))) { + av_log(NULL, AV_LOG_ERROR, "Invalid EntryPoint element found in a Resource\n"); + return ret; + } + } else { + resource->entry_point = 0; + } + + /* read IntrinsicDuration */ + if (!(element = ff_imf_xml_get_child_element_by_name(resource_elem, "IntrinsicDuration"))) { + av_log(NULL, AV_LOG_ERROR, "IntrinsicDuration element missing from Resource\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uint32(element, &resource->duration))) { + av_log(NULL, AV_LOG_ERROR, "Invalid IntrinsicDuration element found in a Resource\n"); + return ret; + } + resource->duration -= resource->entry_point; + + /* read SourceDuration */ + if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "SourceDuration"))) { + if ((ret = ff_imf_xml_read_uint32(element, &resource->duration))) { + av_log(NULL, AV_LOG_ERROR, "SourceDuration element missing from Resource\n"); + return ret; + } + } + + /* read RepeatCount */ + if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "RepeatCount"))) + ret = ff_imf_xml_read_uint32(element, &resource->repeat_count); + + return ret; +} + +static int fill_trackfile_resource(xmlNodePtr tf_resource_elem, + FFIMFTrackFileResource *tf_resource, + FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + int ret = 0; + + if ((ret = fill_base_resource(tf_resource_elem, (FFIMFBaseResource *)tf_resource, cpl))) + return ret; + + /* read TrackFileId */ + if ((element = ff_imf_xml_get_child_element_by_name(tf_resource_elem, "TrackFileId"))) { + if ((ret = ff_imf_xml_read_uuid(element, tf_resource->track_file_uuid))) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackFileId element found in Resource\n"); + return ret; + } + } else { + av_log(NULL, AV_LOG_ERROR, "TrackFileId element missing from Resource\n"); + return AVERROR_INVALIDDATA; + } + + return ret; +} + +static int fill_marker_resource(xmlNodePtr marker_resource_elem, + FFIMFMarkerResource *marker_resource, + FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + int ret = 0; + + if ((ret = fill_base_resource(marker_resource_elem, (FFIMFBaseResource *)marker_resource, cpl))) + return ret; + + /* read markers */ + element = xmlFirstElementChild(marker_resource_elem); + while (element) { + if (xmlStrcmp(element->name, "Marker") == 0) { + void *tmp; + + if (marker_resource->marker_count == UINT32_MAX) + return AVERROR(ENOMEM); + tmp = av_realloc_array(marker_resource->markers, + marker_resource->marker_count + 1, + sizeof(FFIMFMarker)); + if (!tmp) + return AVERROR(ENOMEM); + marker_resource->markers = tmp; + + imf_marker_init(&marker_resource->markers[marker_resource->marker_count]); + ret = fill_marker(element, + &marker_resource->markers[marker_resource->marker_count]); + marker_resource->marker_count++; + if (ret) + return ret; + } + + element = xmlNextElementSibling(element); + } + + return ret; +} + +static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) +{ + int ret = 0; + uint8_t uuid[16]; + xmlNodePtr resource_list_elem = NULL; + xmlNodePtr resource_elem = NULL; + xmlNodePtr track_id_elem = NULL; + unsigned long resource_elem_count; + void *tmp; + + /* read TrackID element */ + if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(marker_sequence_elem, "TrackId"))) { + av_log(NULL, AV_LOG_ERROR, "TrackId element missing from Sequence\n"); + return AVERROR_INVALIDDATA; + } + if (ff_imf_xml_read_uuid(track_id_elem, uuid)) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in Sequence\n"); + return AVERROR_INVALIDDATA; + } + av_log(NULL, + AV_LOG_DEBUG, + "Processing IMF CPL Marker Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", + UID_ARG(uuid)); + + /* create main marker virtual track if it does not exist */ + if (!cpl->main_markers_track) { + cpl->main_markers_track = av_malloc(sizeof(FFIMFMarkerVirtualTrack)); + if (!cpl->main_markers_track) + return AVERROR(ENOMEM); + imf_marker_virtual_track_init(cpl->main_markers_track); + memcpy(cpl->main_markers_track->base.id_uuid, uuid, sizeof(uuid)); + + } else if (memcmp(cpl->main_markers_track->base.id_uuid, uuid, sizeof(uuid)) != 0) { + av_log(NULL, AV_LOG_ERROR, "Multiple marker virtual tracks were found\n"); + return AVERROR_INVALIDDATA; + } + + /* process resources */ + resource_list_elem = ff_imf_xml_get_child_element_by_name(marker_sequence_elem, "ResourceList"); + if (!resource_list_elem) + return 0; + + resource_elem_count = xmlChildElementCount(resource_list_elem); + if (resource_elem_count > UINT32_MAX + || cpl->main_markers_track->resource_count > UINT32_MAX - resource_elem_count) + return AVERROR(ENOMEM); + tmp = av_realloc_array(cpl->main_markers_track->resources, + cpl->main_markers_track->resource_count + resource_elem_count, + sizeof(FFIMFMarkerResource)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate Marker Resources\n"); + return AVERROR(ENOMEM); + } + cpl->main_markers_track->resources = tmp; + + resource_elem = xmlFirstElementChild(resource_list_elem); + while (resource_elem) { + imf_marker_resource_init(&cpl->main_markers_track->resources[cpl->main_markers_track->resource_count]); + ret = fill_marker_resource(resource_elem, + &cpl->main_markers_track->resources[cpl->main_markers_track->resource_count], + cpl); + cpl->main_markers_track->resource_count++; + if (ret) + return ret; + + resource_elem = xmlNextElementSibling(resource_elem); + } + + return ret; +} + +static int has_stereo_resources(xmlNodePtr element) +{ + if (xmlStrcmp(element->name, "Left") == 0 || xmlStrcmp(element->name, "Right") == 0) + return 1; + + element = xmlFirstElementChild(element); + while (element) { + if (has_stereo_resources(element)) + return 1; + + element = xmlNextElementSibling(element); + } + + return 0; +} + +static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cpl) +{ + int ret = 0; + uint8_t uuid[16]; + xmlNodePtr resource_list_elem = NULL; + xmlNodePtr resource_elem = NULL; + xmlNodePtr track_id_elem = NULL; + unsigned long resource_elem_count; + FFIMFTrackFileVirtualTrack *vt = NULL; + void *tmp; + + /* read TrackID element */ + if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(audio_sequence_elem, "TrackId"))) { + av_log(NULL, AV_LOG_ERROR, "TrackId element missing from audio sequence\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uuid(track_id_elem, uuid))) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); + return ret; + } + av_log(NULL, + AV_LOG_DEBUG, + "Processing IMF CPL Audio Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", + UID_ARG(uuid)); + + /* get the main audio virtual track corresponding to the sequence */ + for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) { + if (memcmp(cpl->main_audio_tracks[i].base.id_uuid, uuid, sizeof(uuid)) == 0) { + vt = &cpl->main_audio_tracks[i]; + break; + } + } + + /* create a main audio virtual track if none exists for the sequence */ + if (!vt) { + if (cpl->main_audio_track_count == UINT32_MAX) + return AVERROR(ENOMEM); + tmp = av_realloc_array(cpl->main_audio_tracks, + cpl->main_audio_track_count + 1, + sizeof(FFIMFTrackFileVirtualTrack)); + if (!tmp) + return AVERROR(ENOMEM); + + cpl->main_audio_tracks = tmp; + vt = &cpl->main_audio_tracks[cpl->main_audio_track_count]; + imf_trackfile_virtual_track_init(vt); + cpl->main_audio_track_count++; + memcpy(vt->base.id_uuid, uuid, sizeof(uuid)); + } + + /* process resources */ + resource_list_elem = ff_imf_xml_get_child_element_by_name(audio_sequence_elem, "ResourceList"); + if (!resource_list_elem) + return 0; + + resource_elem_count = xmlChildElementCount(resource_list_elem); + if (resource_elem_count > UINT32_MAX + || vt->resource_count > UINT32_MAX - resource_elem_count) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(vt->resources, + &vt->resources_alloc_sz, + (vt->resource_count + resource_elem_count) + * sizeof(FFIMFTrackFileResource)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Audio Resources\n"); + return AVERROR(ENOMEM); + } + vt->resources = tmp; + + resource_elem = xmlFirstElementChild(resource_list_elem); + while (resource_elem) { + imf_trackfile_resource_init(&vt->resources[vt->resource_count]); + ret = fill_trackfile_resource(resource_elem, + &vt->resources[vt->resource_count], + cpl); + vt->resource_count++; + if (ret) { + av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); + continue; + } + + resource_elem = xmlNextElementSibling(resource_elem); + } + + return ret; +} + +static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL *cpl) +{ + int ret = 0; + uint8_t uuid[16]; + xmlNodePtr resource_list_elem = NULL; + xmlNodePtr resource_elem = NULL; + xmlNodePtr track_id_elem = NULL; + void *tmp; + unsigned long resource_elem_count; + + /* skip stereoscopic resources */ + if (has_stereo_resources(image_sequence_elem)) { + av_log(NULL, AV_LOG_ERROR, "Stereoscopic 3D image virtual tracks not supported\n"); + return AVERROR_PATCHWELCOME; + } + + /* read TrackId element*/ + if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "TrackId"))) { + av_log(NULL, AV_LOG_ERROR, "TrackId element missing from audio sequence\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uuid(track_id_elem, uuid))) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); + return ret; + } + + /* create main image virtual track if one does not exist */ + if (!cpl->main_image_2d_track) { + cpl->main_image_2d_track = av_malloc(sizeof(FFIMFTrackFileVirtualTrack)); + if (!cpl->main_image_2d_track) + return AVERROR(ENOMEM); + imf_trackfile_virtual_track_init(cpl->main_image_2d_track); + memcpy(cpl->main_image_2d_track->base.id_uuid, uuid, sizeof(uuid)); + + } else if (memcmp(cpl->main_image_2d_track->base.id_uuid, uuid, sizeof(uuid)) != 0) { + av_log(NULL, AV_LOG_ERROR, "Multiple MainImage virtual tracks found\n"); + return AVERROR_INVALIDDATA; + } + av_log(NULL, + AV_LOG_DEBUG, + "Processing IMF CPL Main Image Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", + UID_ARG(uuid)); + + /* process resources */ + resource_list_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "ResourceList"); + if (!resource_list_elem) + return 0; + + resource_elem_count = xmlChildElementCount(resource_list_elem); + if (resource_elem_count > UINT32_MAX + || cpl->main_image_2d_track->resource_count > UINT32_MAX - resource_elem_count + || (cpl->main_image_2d_track->resource_count + resource_elem_count) + > INT_MAX / sizeof(FFIMFTrackFileResource)) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(cpl->main_image_2d_track->resources, + &cpl->main_image_2d_track->resources_alloc_sz, + (cpl->main_image_2d_track->resource_count + resource_elem_count) + * sizeof(FFIMFTrackFileResource)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Image Resources\n"); + return AVERROR(ENOMEM); + } + cpl->main_image_2d_track->resources = tmp; + + resource_elem = xmlFirstElementChild(resource_list_elem); + while (resource_elem) { + imf_trackfile_resource_init( + &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count]); + ret = fill_trackfile_resource(resource_elem, + &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count], + cpl); + cpl->main_image_2d_track->resource_count++; + if (ret) { + av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); + continue; + } + + resource_elem = xmlNextElementSibling(resource_elem); + } + + return 0; +} + +static int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + int ret = 0; + xmlNodePtr segment_list_elem = NULL; + xmlNodePtr segment_elem = NULL; + xmlNodePtr sequence_list_elem = NULL; + xmlNodePtr sequence_elem = NULL; + + if (!(segment_list_elem = ff_imf_xml_get_child_element_by_name(cpl_element, "SegmentList"))) { + av_log(NULL, AV_LOG_ERROR, "SegmentList element missing\n"); + return AVERROR_INVALIDDATA; + } + + /* process sequences */ + segment_elem = xmlFirstElementChild(segment_list_elem); + while (segment_elem) { + av_log(NULL, AV_LOG_DEBUG, "Processing IMF CPL Segment\n"); + + sequence_list_elem = ff_imf_xml_get_child_element_by_name(segment_elem, "SequenceList"); + if (!segment_list_elem) + continue; + + sequence_elem = xmlFirstElementChild(sequence_list_elem); + while (sequence_elem) { + if (xmlStrcmp(sequence_elem->name, "MarkerSequence") == 0) + ret = push_marker_sequence(sequence_elem, cpl); + + else if (xmlStrcmp(sequence_elem->name, "MainImageSequence") == 0) + ret = push_main_image_2d_sequence(sequence_elem, cpl); + + else if (xmlStrcmp(sequence_elem->name, "MainAudioSequence") == 0) + ret = push_main_audio_sequence(sequence_elem, cpl); + + else + av_log(NULL, + AV_LOG_INFO, + "The following Sequence is not supported and is ignored: %s\n", + sequence_elem->name); + + /* abort parsing only if memory error occurred */ + if (ret == AVERROR(ENOMEM)) + return ret; + + sequence_elem = xmlNextElementSibling(sequence_elem); + } + + segment_elem = xmlNextElementSibling(segment_elem); + } + + return ret; +} + +int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl) +{ + int ret = 0; + xmlNodePtr cpl_element = NULL; + + *cpl = ff_imf_cpl_alloc(); + if (!*cpl) { + ret = AVERROR(ENOMEM); + goto cleanup; + } + + cpl_element = xmlDocGetRootElement(doc); + if (xmlStrcmp(cpl_element->name, "CompositionPlaylist")) { + av_log(NULL, AV_LOG_ERROR, "The root element of the CPL is not CompositionPlaylist\n"); + ret = AVERROR_INVALIDDATA; + goto cleanup; + } + + if ((ret = fill_content_title(cpl_element, *cpl))) + goto cleanup; + if ((ret = fill_id(cpl_element, *cpl))) + goto cleanup; + if ((ret = fill_edit_rate(cpl_element, *cpl))) + goto cleanup; + if ((ret = fill_virtual_tracks(cpl_element, *cpl))) + goto cleanup; + +cleanup: + if (*cpl && ret) { + ff_imf_cpl_free(*cpl); + *cpl = NULL; + } + return ret; +} + +static void imf_marker_free(FFIMFMarker *marker) +{ + if (!marker) + return; + xmlFree(marker->label_utf8); + xmlFree(marker->scope_utf8); +} + +static void imf_marker_resource_free(FFIMFMarkerResource *rsrc) +{ + if (!rsrc) + return; + for (uint32_t i = 0; i < rsrc->marker_count; i++) + imf_marker_free(&rsrc->markers[i]); + av_freep(&rsrc->markers); +} + +static void imf_marker_virtual_track_free(FFIMFMarkerVirtualTrack *vt) +{ + if (!vt) + return; + for (uint32_t i = 0; i < vt->resource_count; i++) + imf_marker_resource_free(&vt->resources[i]); + av_freep(&vt->resources); +} + +static void imf_trackfile_virtual_track_free(FFIMFTrackFileVirtualTrack *vt) +{ + if (!vt) + return; + av_freep(&vt->resources); +} + +static void imf_cpl_init(FFIMFCPL *cpl) +{ + memset(cpl->id_uuid, 0, sizeof(cpl->id_uuid)); + cpl->content_title_utf8 = NULL; + cpl->edit_rate = av_make_q(0, 1); + cpl->main_markers_track = NULL; + cpl->main_image_2d_track = NULL; + cpl->main_audio_track_count = 0; + cpl->main_audio_tracks = NULL; +} + +FFIMFCPL *ff_imf_cpl_alloc(void) +{ + FFIMFCPL *cpl; + + cpl = av_malloc(sizeof(FFIMFCPL)); + if (!cpl) + return NULL; + imf_cpl_init(cpl); + return cpl; +} + +void ff_imf_cpl_free(FFIMFCPL *cpl) +{ + if (!cpl) + return; + + xmlFree(cpl->content_title_utf8); + + imf_marker_virtual_track_free(cpl->main_markers_track); + + if (cpl->main_markers_track) + av_freep(&cpl->main_markers_track); + + imf_trackfile_virtual_track_free(cpl->main_image_2d_track); + + if (cpl->main_image_2d_track) + av_freep(&cpl->main_image_2d_track); + + for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) + imf_trackfile_virtual_track_free(&cpl->main_audio_tracks[i]); + + if (cpl->main_audio_tracks) + av_freep(&cpl->main_audio_tracks); + + av_freep(&cpl); +} + +int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) +{ + AVBPrint buf; + xmlDoc *doc = NULL; + int ret = 0; + int64_t filesize = 0; + + filesize = avio_size(in); + filesize = filesize > 0 ? filesize : 8192; + av_bprint_init(&buf, filesize + 1, AV_BPRINT_SIZE_UNLIMITED); + ret = avio_read_to_bprint(in, &buf, UINT_MAX - 1); + if (ret < 0 || !avio_feof(in) || buf.len == 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot read IMF CPL\n"); + if (ret == 0) + ret = AVERROR_INVALIDDATA; + } else { + LIBXML_TEST_VERSION + + filesize = buf.len; + doc = xmlReadMemory(buf.str, filesize, NULL, NULL, 0); + if (!doc) { + av_log(NULL, + AV_LOG_ERROR, + "XML parsing failed when reading the IMF CPL\n"); + ret = AVERROR_INVALIDDATA; + } + + if ((ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl))) { + av_log(NULL, AV_LOG_ERROR, "Cannot parse IMF CPL\n"); + } else { + av_log(NULL, + AV_LOG_INFO, + "IMF CPL ContentTitle: %s\n", + (*cpl)->content_title_utf8); + av_log(NULL, + AV_LOG_INFO, + "IMF CPL Id: " FF_IMF_UUID_FORMAT "\n", + UID_ARG((*cpl)->id_uuid)); + } + + xmlFreeDoc(doc); + } + + av_bprint_finalize(&buf, NULL); + + return ret; +} diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c new file mode 100644 index 0000000000..f17064cfcd --- /dev/null +++ b/libavformat/imfdec.c @@ -0,0 +1,899 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * + * Copyright (c) Sandflow Consulting LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Demuxes an IMF Composition + * + * References + * OV 2067-0:2018 - SMPTE Overview Document - Interoperable Master Format + * ST 2067-2:2020 - SMPTE Standard - Interoperable Master Format — Core Constraints + * ST 2067-3:2020 - SMPTE Standard - Interoperable Master Format — Composition Playlist + * ST 2067-5:2020 - SMPTE Standard - Interoperable Master Format — Essence Component + * ST 2067-20:2016 - SMPTE Standard - Interoperable Master Format — Application #2 + * ST 2067-21:2020 - SMPTE Standard - Interoperable Master Format — Application #2 Extended + * ST 2067-102:2017 - SMPTE Standard - Interoperable Master Format — Common Image Pixel Color Schemes + * ST 429-9:2007 - SMPTE Standard - D-Cinema Packaging — Asset Mapping and File Segmentation + * + * @author Marc-Antoine Arnaud + * @author Valentin Noel + * @author Nicholas Vanderzwet + * @file + * @ingroup lavu_imf + */ + +#include "avio_internal.h" +#include "imf.h" +#include "internal.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/opt.h" +#include "mxf.h" +#include "url.h" +#include +#include + +#define MAX_BPRINT_READ_SIZE (UINT_MAX - 1) +#define DEFAULT_ASSETMAP_SIZE 8 * 1024 +#define AVRATIONAL_FORMAT "%d/%d" +#define AVRATIONAL_ARG(rational) rational.num, rational.den + +/** + * IMF Asset locator + */ +typedef struct IMFAssetLocator { + FFIMFUUID uuid; + char *absolute_uri; +} IMFAssetLocator; + +/** + * IMF Asset locator map + * Results from the parsing of one or more ASSETMAP XML files + */ +typedef struct IMFAssetLocatorMap { + uint32_t asset_count; + IMFAssetLocator *assets; +} IMFAssetLocatorMap; + +typedef struct IMFVirtualTrackResourcePlaybackCtx { + IMFAssetLocator *locator; + FFIMFTrackFileResource *resource; + AVFormatContext *ctx; +} IMFVirtualTrackResourcePlaybackCtx; + +typedef struct IMFVirtualTrackPlaybackCtx { + int32_t index; /**< Track index in playlist */ + AVRational current_timestamp; /**< Current temporal position */ + AVRational duration; /**< Overall duration */ + uint32_t resource_count; /**< Number of resources */ + unsigned int resources_alloc_sz; /**< Size of the buffer holding the resource */ + IMFVirtualTrackResourcePlaybackCtx *resources; /**< Buffer holding the resources */ + uint32_t current_resource_index; /**< Current resource */ + int64_t last_pts; /**< Last timestamp */ +} IMFVirtualTrackPlaybackCtx; + +typedef struct IMFContext { + const AVClass *class; + const char *base_url; + char *asset_map_paths; + AVIOInterruptCB *interrupt_callback; + AVDictionary *avio_opts; + FFIMFCPL *cpl; + IMFAssetLocatorMap asset_locator_map; + uint32_t track_count; + IMFVirtualTrackPlaybackCtx **tracks; +} IMFContext; + +static int imf_uri_is_url(const char *string) +{ + return strstr(string, "://") != NULL; +} + +static int imf_uri_is_unix_abs_path(const char *string) +{ + return string[0] == '/'; +} + +static int imf_uri_is_dos_abs_path(const char *string) +{ + /* Absolute path case: `C:\path\to\somwhere` */ + if (string[1] == ':' && string[2] == '\\') + return 1; + + /* Absolute path case: `C:/path/to/somwhere` */ + if (string[1] == ':' && string[2] == '/') + return 1; + + /* Network path case: `\\path\to\somwhere` */ + if (string[0] == '\\' && string[1] == '\\') + return 1; + + return 0; +} + +/** + * Parse a ASSETMAP XML file to extract the UUID-URI mapping of assets. + * @param s the current format context, if any (can be NULL). + * @param doc the XML document to be parsed. + * @param asset_map pointer on the IMFAssetLocatorMap to fill. + * @param base_url the url of the asset map XML file, if any (can be NULL). + * @return a negative value in case of error, 0 otherwise. + */ +static int parse_imf_asset_map_from_xml_dom(AVFormatContext *s, + xmlDocPtr doc, + IMFAssetLocatorMap *asset_map, + const char *base_url) +{ + xmlNodePtr asset_map_element = NULL; + xmlNodePtr node = NULL; + xmlNodePtr asset_element = NULL; + unsigned long elem_count; + char *uri; + int ret = 0; + IMFAssetLocator *asset = NULL; + void *tmp; + + asset_map_element = xmlDocGetRootElement(doc); + + if (!asset_map_element) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing root node\n"); + return AVERROR_INVALIDDATA; + } + + if (asset_map_element->type != XML_ELEMENT_NODE || av_strcasecmp(asset_map_element->name, "AssetMap")) { + av_log(s, + AV_LOG_ERROR, + "Unable to parse asset map XML - wrong root node name[%s] type[%d]\n", + asset_map_element->name, + (int)asset_map_element->type); + return AVERROR_INVALIDDATA; + } + + /* parse asset locators */ + if (!(node = ff_imf_xml_get_child_element_by_name(asset_map_element, "AssetList"))) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing AssetList node\n"); + return AVERROR_INVALIDDATA; + } + elem_count = xmlChildElementCount(node); + if (elem_count > UINT32_MAX + || asset_map->asset_count > UINT32_MAX - elem_count) + return AVERROR(ENOMEM); + tmp = av_realloc_array(asset_map->assets, + elem_count + asset_map->asset_count, + sizeof(IMFAssetLocator)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate IMF asset locators\n"); + return AVERROR(ENOMEM); + } + asset_map->assets = tmp; + + asset_element = xmlFirstElementChild(node); + while (asset_element) { + if (av_strcasecmp(asset_element->name, "Asset") != 0) + continue; + + asset = &(asset_map->assets[asset_map->asset_count]); + + if (ff_imf_xml_read_uuid(ff_imf_xml_get_child_element_by_name(asset_element, "Id"), asset->uuid)) { + av_log(s, AV_LOG_ERROR, "Could not parse UUID from asset in asset map.\n"); + return AVERROR_INVALIDDATA; + } + + av_log(s, AV_LOG_DEBUG, "Found asset id: " FF_IMF_UUID_FORMAT "\n", UID_ARG(asset->uuid)); + + if (!(node = ff_imf_xml_get_child_element_by_name(asset_element, "ChunkList"))) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing ChunkList node\n"); + return AVERROR_INVALIDDATA; + } + + if (!(node = ff_imf_xml_get_child_element_by_name(node, "Chunk"))) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing Chunk node\n"); + return AVERROR_INVALIDDATA; + } + + uri = xmlNodeGetContent(ff_imf_xml_get_child_element_by_name(node, "Path")); + if (!imf_uri_is_url(uri) && !imf_uri_is_unix_abs_path(uri) && !imf_uri_is_dos_abs_path(uri)) + asset->absolute_uri = av_append_path_component(base_url, uri); + else + asset->absolute_uri = av_strdup(uri); + xmlFree(uri); + if (!asset->absolute_uri) + return AVERROR(ENOMEM); + + av_log(s, AV_LOG_DEBUG, "Found asset absolute URI: %s\n", asset->absolute_uri); + + asset_map->asset_count++; + asset_element = xmlNextElementSibling(asset_element); + } + + return ret; +} + +/** + * Initializes an IMFAssetLocatorMap structure. + */ +static void imf_asset_locator_map_init(IMFAssetLocatorMap *asset_map) +{ + asset_map->assets = NULL; + asset_map->asset_count = 0; +} + +/** + * Free a IMFAssetLocatorMap pointer. + */ +static void imf_asset_locator_map_deinit(IMFAssetLocatorMap *asset_map) +{ + for (uint32_t i = 0; i < asset_map->asset_count; ++i) + av_freep(&asset_map->assets[i].absolute_uri); + + av_freep(&asset_map->assets); +} + +static int parse_assetmap(AVFormatContext *s, const char *url) +{ + IMFContext *c = s->priv_data; + AVIOContext *in = NULL; + struct AVBPrint buf; + AVDictionary *opts = NULL; + xmlDoc *doc = NULL; + const char *base_url; + char *tmp_str = NULL; + int ret; + int64_t filesize; + + av_log(s, AV_LOG_DEBUG, "Asset Map URL: %s\n", url); + + av_dict_copy(&opts, c->avio_opts, 0); + ret = s->io_open(s, &in, url, AVIO_FLAG_READ, &opts); + av_dict_free(&opts); + if (ret < 0) + return ret; + + filesize = avio_size(in); + filesize = filesize > 0 ? filesize : DEFAULT_ASSETMAP_SIZE; + + av_bprint_init(&buf, filesize + 1, AV_BPRINT_SIZE_UNLIMITED); + + ret = avio_read_to_bprint(in, &buf, MAX_BPRINT_READ_SIZE); + if (ret < 0 || !avio_feof(in) || buf.len == 0) { + av_log(s, AV_LOG_ERROR, "Unable to read to asset map '%s'\n", url); + if (ret == 0) + ret = AVERROR_INVALIDDATA; + goto clean_up; + } + + LIBXML_TEST_VERSION + + tmp_str = av_strdup(url); + if (!tmp_str) { + ret = AVERROR(ENOMEM); + goto clean_up; + } + base_url = av_dirname(tmp_str); + + filesize = buf.len; + doc = xmlReadMemory(buf.str, filesize, url, NULL, 0); + + ret = parse_imf_asset_map_from_xml_dom(s, doc, &c->asset_locator_map, base_url); + if (!ret) + av_log(s, + AV_LOG_DEBUG, + "Found %d assets from %s\n", + c->asset_locator_map.asset_count, + url); + + xmlFreeDoc(doc); + +clean_up: + if (tmp_str) + av_freep(&tmp_str); + ff_format_io_close(s, &in); + av_bprint_finalize(&buf, NULL); + return ret; +} + +static IMFAssetLocator *find_asset_map_locator(IMFAssetLocatorMap *asset_map, FFIMFUUID uuid) +{ + for (uint32_t i = 0; i < asset_map->asset_count; ++i) { + if (memcmp(asset_map->assets[i].uuid, uuid, 16) == 0) + return &(asset_map->assets[i]); + } + return NULL; +} + +static int open_track_resource_context(AVFormatContext *s, + IMFVirtualTrackResourcePlaybackCtx *track_resource) +{ + IMFContext *c = s->priv_data; + int ret = 0; + int64_t entry_point; + AVDictionary *opts = NULL; + + if (track_resource->ctx) { + av_log(s, + AV_LOG_DEBUG, + "Input context already opened for %s.\n", + track_resource->locator->absolute_uri); + return 0; + } + + track_resource->ctx = avformat_alloc_context(); + if (!track_resource->ctx) + return AVERROR(ENOMEM); + + track_resource->ctx->io_open = s->io_open; + track_resource->ctx->io_close = s->io_close; + track_resource->ctx->io_close2 = s->io_close2; + track_resource->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO; + + if ((ret = ff_copy_whiteblacklists(track_resource->ctx, s)) < 0) + goto cleanup; + + if ((ret = av_opt_set(track_resource->ctx, "format_whitelist", "mxf", 0))) + goto cleanup; + + if ((ret = av_dict_copy(&opts, c->avio_opts, 0)) < 0) + goto cleanup; + + ret = avformat_open_input(&track_resource->ctx, + track_resource->locator->absolute_uri, + NULL, + &opts); + if (ret < 0) { + av_log(s, + AV_LOG_ERROR, + "Could not open %s input context: %s\n", + track_resource->locator->absolute_uri, + av_err2str(ret)); + goto cleanup; + } + av_dict_free(&opts); + + /* Compare the source timebase to the resource edit rate, + * considering the first stream of the source file + */ + if (av_cmp_q(track_resource->ctx->streams[0]->time_base, + av_inv_q(track_resource->resource->base.edit_rate))) + av_log(s, + AV_LOG_WARNING, + "Incoherent source stream timebase %d/%d regarding resource edit rate: %d/%d", + track_resource->ctx->streams[0]->time_base.num, + track_resource->ctx->streams[0]->time_base.den, + track_resource->resource->base.edit_rate.den, + track_resource->resource->base.edit_rate.num); + + entry_point = (int64_t)track_resource->resource->base.entry_point + * track_resource->resource->base.edit_rate.den + * AV_TIME_BASE + / track_resource->resource->base.edit_rate.num; + + if (entry_point) { + av_log(s, + AV_LOG_DEBUG, + "Seek at resource %s entry point: %" PRIu32 "\n", + track_resource->locator->absolute_uri, + track_resource->resource->base.entry_point); + ret = avformat_seek_file(track_resource->ctx, -1, entry_point, entry_point, entry_point, 0); + if (ret < 0) { + av_log(s, + AV_LOG_ERROR, + "Could not seek at %" PRId64 "on %s: %s\n", + entry_point, + track_resource->locator->absolute_uri, + av_err2str(ret)); + avformat_close_input(&track_resource->ctx); + return ret; + } + } + + return 0; + +cleanup: + av_dict_free(&opts); + avformat_free_context(track_resource->ctx); + track_resource->ctx = NULL; + return ret; +} + +static int open_track_file_resource(AVFormatContext *s, + FFIMFTrackFileResource *track_file_resource, + IMFVirtualTrackPlaybackCtx *track) +{ + IMFContext *c = s->priv_data; + IMFAssetLocator *asset_locator; + void *tmp; + int ret; + + asset_locator = find_asset_map_locator(&c->asset_locator_map, track_file_resource->track_file_uuid); + if (!asset_locator) { + av_log(s, + AV_LOG_ERROR, + "Could not find asset locator for UUID: " FF_IMF_UUID_FORMAT "\n", + UID_ARG(track_file_resource->track_file_uuid)); + return AVERROR_INVALIDDATA; + } + + av_log(s, + AV_LOG_DEBUG, + "Found locator for " FF_IMF_UUID_FORMAT ": %s\n", + UID_ARG(asset_locator->uuid), + asset_locator->absolute_uri); + + if (track->resource_count > UINT32_MAX - track_file_resource->base.repeat_count + || (track->resource_count + track_file_resource->base.repeat_count) + > INT_MAX / sizeof(IMFVirtualTrackResourcePlaybackCtx)) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(track->resources, + &track->resources_alloc_sz, + (track->resource_count + track_file_resource->base.repeat_count) + * sizeof(IMFVirtualTrackResourcePlaybackCtx)); + if (!tmp) + return AVERROR(ENOMEM); + track->resources = tmp; + + for (uint32_t i = 0; i < track_file_resource->base.repeat_count; ++i) { + IMFVirtualTrackResourcePlaybackCtx vt_ctx; + + vt_ctx.locator = asset_locator; + vt_ctx.resource = track_file_resource; + vt_ctx.ctx = NULL; + if ((ret = open_track_resource_context(s, &vt_ctx)) != 0) + return ret; + track->resources[track->resource_count++] = vt_ctx; + track->duration = av_add_q(track->duration, + av_make_q((int)track_file_resource->base.duration + * track_file_resource->base.edit_rate.den, + track_file_resource->base.edit_rate.num)); + } + + return 0; +} + +static void imf_virtual_track_playback_context_deinit(IMFVirtualTrackPlaybackCtx *track) +{ + for (uint32_t i = 0; i < track->resource_count; ++i) + avformat_close_input(&track->resources[i].ctx); + + av_freep(&track->resources); +} + +static int open_virtual_track(AVFormatContext *s, + FFIMFTrackFileVirtualTrack *virtual_track, + int32_t track_index) +{ + IMFContext *c = s->priv_data; + IMFVirtualTrackPlaybackCtx *track = NULL; + void *tmp; + int ret = 0; + + if (!(track = av_mallocz(sizeof(IMFVirtualTrackPlaybackCtx)))) + return AVERROR(ENOMEM); + track->index = track_index; + track->duration = av_make_q(0, 1); + + for (uint32_t i = 0; i < virtual_track->resource_count; i++) { + av_log(s, + AV_LOG_DEBUG, + "Open stream from file " FF_IMF_UUID_FORMAT ", stream %d\n", + UID_ARG(virtual_track->resources[i].track_file_uuid), + i); + if ((ret = open_track_file_resource(s, &virtual_track->resources[i], track)) != 0) { + av_log(s, + AV_LOG_ERROR, + "Could not open image track resource " FF_IMF_UUID_FORMAT "\n", + UID_ARG(virtual_track->resources[i].track_file_uuid)); + goto clean_up; + } + } + + track->current_timestamp = av_make_q(0, track->duration.den); + + if (c->track_count == UINT32_MAX) { + ret = AVERROR(ENOMEM); + goto clean_up; + } + tmp = av_realloc_array(c->tracks, c->track_count + 1, sizeof(IMFVirtualTrackPlaybackCtx *)); + if (!tmp) { + ret = AVERROR(ENOMEM); + goto clean_up; + } + c->tracks = tmp; + c->tracks[c->track_count++] = track; + + return 0; + +clean_up: + imf_virtual_track_playback_context_deinit(track); + av_free(track); + return ret; +} + +static int set_context_streams_from_tracks(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + int ret = 0; + + for (uint32_t i = 0; i < c->track_count; ++i) { + AVStream *asset_stream; + AVStream *first_resource_stream; + + /* Open the first resource of the track to get stream information */ + first_resource_stream = c->tracks[i]->resources[0].ctx->streams[0]; + av_log(s, AV_LOG_DEBUG, "Open the first resource of track %d\n", c->tracks[i]->index); + + /* Copy stream information */ + asset_stream = avformat_new_stream(s, NULL); + if (!asset_stream) { + ret = AVERROR(ENOMEM); + av_log(s, AV_LOG_ERROR, "Could not create stream\n"); + break; + } + asset_stream->id = i; + ret = avcodec_parameters_copy(asset_stream->codecpar, first_resource_stream->codecpar); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Could not copy stream parameters\n"); + return ret; + } + avpriv_set_pts_info(asset_stream, + first_resource_stream->pts_wrap_bits, + first_resource_stream->time_base.num, + first_resource_stream->time_base.den); + asset_stream->duration = (int64_t)av_q2d(av_mul_q(c->tracks[i]->duration, + av_inv_q(asset_stream->time_base))); + } + + return 0; +} + +static int open_cpl_tracks(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + int32_t track_index = 0; + int ret; + + if (c->cpl->main_image_2d_track) { + if ((ret = open_virtual_track(s, c->cpl->main_image_2d_track, track_index++)) != 0) { + av_log(s, + AV_LOG_ERROR, + "Could not open image track " FF_IMF_UUID_FORMAT "\n", + UID_ARG(c->cpl->main_image_2d_track->base.id_uuid)); + return ret; + } + } + + for (uint32_t i = 0; i < c->cpl->main_audio_track_count; ++i) { + if ((ret = open_virtual_track(s, &c->cpl->main_audio_tracks[i], track_index++)) != 0) { + av_log(s, + AV_LOG_ERROR, + "Could not open audio track " FF_IMF_UUID_FORMAT "\n", + UID_ARG(c->cpl->main_audio_tracks[i].base.id_uuid)); + return ret; + } + } + + return set_context_streams_from_tracks(s); +} + +static int imf_read_header(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + char *asset_map_path; + char *tmp_str; + int ret = 0; + + c->interrupt_callback = &s->interrupt_callback; + tmp_str = av_strdup(s->url); + if (!tmp_str) + return AVERROR(ENOMEM); + + c->base_url = av_dirname(tmp_str); + if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) + return ret; + + av_log(s, AV_LOG_DEBUG, "start parsing IMF CPL: %s\n", s->url); + + if ((ret = ff_imf_parse_cpl(s->pb, &c->cpl)) < 0) + return ret; + + av_log(s, + AV_LOG_DEBUG, + "parsed IMF CPL: " FF_IMF_UUID_FORMAT "\n", + UID_ARG(c->cpl->id_uuid)); + + if (!c->asset_map_paths) { + c->asset_map_paths = av_append_path_component(c->base_url, "ASSETMAP.xml"); + if (!c->asset_map_paths) { + ret = AVERROR(ENOMEM); + return ret; + } + av_log(s, AV_LOG_DEBUG, "No asset maps provided, using the default ASSETMAP.xml\n"); + } + + /* Parse each asset map XML file */ + imf_asset_locator_map_init(&c->asset_locator_map); + asset_map_path = av_strtok(c->asset_map_paths, ",", &tmp_str); + while (asset_map_path != NULL) { + av_log(s, AV_LOG_DEBUG, "start parsing IMF Asset Map: %s\n", asset_map_path); + + if ((ret = parse_assetmap(s, asset_map_path))) + return ret; + + asset_map_path = av_strtok(NULL, ",", &tmp_str); + } + + av_log(s, AV_LOG_DEBUG, "parsed IMF Asset Maps\n"); + + if ((ret = open_cpl_tracks(s))) + return ret; + + av_log(s, AV_LOG_DEBUG, "parsed IMF package\n"); + + return 0; +} + +static IMFVirtualTrackPlaybackCtx *get_next_track_with_minimum_timestamp(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + IMFVirtualTrackPlaybackCtx *track; + + AVRational minimum_timestamp = av_make_q(INT32_MAX, 1); + for (uint32_t i = c->track_count; i > 0; i--) { + av_log(s, + AV_LOG_DEBUG, + "Compare track %d timestamp " AVRATIONAL_FORMAT + " to minimum " AVRATIONAL_FORMAT + " (over duration: " AVRATIONAL_FORMAT + ")\n", + i, + AVRATIONAL_ARG(c->tracks[i - 1]->current_timestamp), + AVRATIONAL_ARG(minimum_timestamp), + AVRATIONAL_ARG(c->tracks[i - 1]->duration)); + + if (av_cmp_q(c->tracks[i - 1]->current_timestamp, minimum_timestamp) <= 0) { + track = c->tracks[i - 1]; + minimum_timestamp = track->current_timestamp; + } + } + + av_log(s, + AV_LOG_DEBUG, + "Found next track to read: %d (timestamp: %lf / %lf)\n", + track->index, + av_q2d(track->current_timestamp), + av_q2d(minimum_timestamp)); + return track; +} + +static IMFVirtualTrackResourcePlaybackCtx *get_resource_context_for_timestamp(AVFormatContext *s, + IMFVirtualTrackPlaybackCtx *track) +{ + AVRational edit_unit_duration = av_inv_q(track->resources[0].resource->base.edit_rate); + AVRational cumulated_duration = av_make_q(0, edit_unit_duration.den); + + av_log(s, + AV_LOG_DEBUG, + "Looking for track %d resource for timestamp = %lf / %lf\n", + track->index, + av_q2d(track->current_timestamp), + av_q2d(track->duration)); + for (uint32_t i = 0; i < track->resource_count; ++i) { + cumulated_duration = av_add_q(cumulated_duration, + av_make_q((int)track->resources[i].resource->base.duration + * edit_unit_duration.num, + edit_unit_duration.den)); + + if (av_cmp_q(av_add_q(track->current_timestamp, edit_unit_duration), cumulated_duration) <= 0) { + av_log(s, + AV_LOG_DEBUG, + "Found resource %d in track %d to read for timestamp %lf " + "(on cumulated=%lf): entry=%" PRIu32 + ", duration=%" PRIu32 + ", editrate=" AVRATIONAL_FORMAT + " | edit_unit_duration=%lf\n", + i, + track->index, + av_q2d(track->current_timestamp), + av_q2d(cumulated_duration), + track->resources[i].resource->base.entry_point, + track->resources[i].resource->base.duration, + AVRATIONAL_ARG(track->resources[i].resource->base.edit_rate), + av_q2d(edit_unit_duration)); + + if (track->current_resource_index != i) { + av_log(s, + AV_LOG_DEBUG, + "Switch resource on track %d: re-open context\n", + track->index); + if (open_track_resource_context(s, &(track->resources[i])) != 0) + return NULL; + avformat_close_input(&(track->resources[track->current_resource_index].ctx)); + track->current_resource_index = i; + } + + return &(track->resources[track->current_resource_index]); + } + } + return NULL; +} + +static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + IMFContext *c = s->priv_data; + IMFVirtualTrackResourcePlaybackCtx *resource_to_read = NULL; + AVRational edit_unit_duration; + int ret = 0; + IMFVirtualTrackPlaybackCtx *track; + FFStream *track_stream; + + track = get_next_track_with_minimum_timestamp(s); + + if (av_cmp_q(track->current_timestamp, track->duration) == 0) + return AVERROR_EOF; + + resource_to_read = get_resource_context_for_timestamp(s, track); + + if (!resource_to_read) { + edit_unit_duration + = av_inv_q(track->resources[track->current_resource_index].resource->base.edit_rate); + + if (av_cmp_q(av_add_q(track->current_timestamp, edit_unit_duration), track->duration) > 0) + return AVERROR_EOF; + + av_log(s, AV_LOG_ERROR, "Could not find IMF track resource to read\n"); + return AVERROR_STREAM_NOT_FOUND; + } + + while (!ff_check_interrupt(c->interrupt_callback) && !ret) { + ret = av_read_frame(resource_to_read->ctx, pkt); + av_log(s, + AV_LOG_DEBUG, + "Got packet: pts=%" PRId64 + ", dts=%" PRId64 + ", duration=%" PRId64 + ", stream_index=%d, pos=%" PRId64 + "\n", + pkt->pts, + pkt->dts, + pkt->duration, + pkt->stream_index, + pkt->pos); + + track_stream = ffstream(s->streams[track->index]); + if (ret >= 0) { + /* Update packet info from track */ + if (pkt->dts < track_stream->cur_dts && track->last_pts > 0) + pkt->dts = track_stream->cur_dts; + + pkt->pts = track->last_pts; + pkt->dts = pkt->dts + - (int64_t)track->resources[track->current_resource_index].resource->base.entry_point; + pkt->stream_index = track->index; + + /* Update track cursors */ + track->current_timestamp + = av_add_q(track->current_timestamp, + av_make_q((int)pkt->duration + * resource_to_read->ctx->streams[0]->time_base.num, + resource_to_read->ctx->streams[0]->time_base.den)); + track->last_pts += pkt->duration; + + return 0; + } else if (ret != AVERROR_EOF) { + av_log(s, + AV_LOG_ERROR, + "Could not get packet from track %d: %s\n", + track->index, + av_err2str(ret)); + return ret; + } + } + + return AVERROR_EOF; +} + +static int imf_close(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + + av_log(s, AV_LOG_DEBUG, "Close IMF package\n"); + av_dict_free(&c->avio_opts); + av_freep(&c->base_url); + imf_asset_locator_map_deinit(&c->asset_locator_map); + ff_imf_cpl_free(c->cpl); + + for (uint32_t i = 0; i < c->track_count; ++i) { + imf_virtual_track_playback_context_deinit(c->tracks[i]); + av_freep(&c->tracks[i]); + } + + av_freep(&c->tracks); + + return 0; +} + +static int imf_probe(const AVProbeData *p) +{ + if (!strstr(p->buf, "buf, "ContentTitle>")) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static const AVOption imf_options[] = { + { + .name = "assetmaps", + .help = "Comma-separated paths to ASSETMAP files." + "If not specified, the `ASSETMAP.xml` file in the same " + "directory as the CPL is used.", + .offset = offsetof(IMFContext, asset_map_paths), + .type = AV_OPT_TYPE_STRING, + .default_val = {.str = NULL}, + .flags = AV_OPT_FLAG_DECODING_PARAM, + }, + {NULL}, +}; + +static const AVClass imf_class = { + .class_name = "imf", + .item_name = av_default_item_name, + .option = imf_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVInputFormat ff_imf_demuxer = { + .name = "imf", + .long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"), + .flags_internal = FF_FMT_INIT_CLEANUP, + .priv_class = &imf_class, + .priv_data_size = sizeof(IMFContext), + .read_probe = imf_probe, + .read_header = imf_read_header, + .read_packet = imf_read_packet, + .read_close = imf_close, +}; diff --git a/libavformat/version.h b/libavformat/version.h index 9b90bbf156..917b9ffa5d 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 11 +#define LIBAVFORMAT_VERSION_MINOR 12 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 6b7e4de0dbc78a630bfea27e917798b4d5b61abf Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Sun, 26 Dec 2021 16:47:58 -0800 Subject: [PATCH 655/894] avformat/imf: Tests Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/Makefile | 1 + libavformat/tests/imf.c | 526 +++++++++++++++++++++++++++++++++++++ tests/fate/libavformat.mak | 4 + tests/ref/fate/imf | 54 ++++ 4 files changed, 585 insertions(+) create mode 100644 libavformat/tests/imf.c create mode 100644 tests/ref/fate/imf diff --git a/libavformat/Makefile b/libavformat/Makefile index 74b1c56351..10d1a89083 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -698,6 +698,7 @@ TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh TESTPROGS-$(CONFIG_MOV_MUXER) += movenc TESTPROGS-$(CONFIG_NETWORK) += noproxy TESTPROGS-$(CONFIG_SRTP) += srtp +TESTPROGS-$(CONFIG_IMF_DEMUXER) += imf TOOLS = aviocat \ ismindex \ diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c new file mode 100644 index 0000000000..68e4c8b6af --- /dev/null +++ b/libavformat/tests/imf.c @@ -0,0 +1,526 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * + * Copyright (c) Sandflow Consulting LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Tests for IMF CPL and ASSETMAP processing + * + * @author Valentin Noel + * @author Pierre-Anthony Lemieux + * @file + * @ingroup lavu_imf + */ + +#include "libavformat/imf_cpl.c" +#include "libavformat/imfdec.c" +#include "libavformat/mxf.h" + +#include + +const char *cpl_doc = + "" + "urn:uuid:8713c020-2489-45f5-a9f7-87be539e20b5" + "2021-07-13T17:06:22Z" + "FFMPEG" + "FFMPEG sample content" + "" + " " + " urn:uuid:8e097bb0-cff7-4969-a692-bad47bfb528f" + " " + "" + "24000 1001" + "" + "" + "urn:uuid:81fed4e5-9722-400a-b9d1-7f2bd21df4b6" + "" + "" + "urn:uuid:16327185-9205-47ef-a17b-ee28df251db7" + "urn:uuid:461f5424-8f6e-48a9-a385-5eda46fda381" + "" + "" + "urn:uuid:ea3d0f23-55d6-4e03-86ec-cfe0666f0e6a" + "24" + "" + "" + "5" + "" + "" + "" + "" + "" + "urn:uuid:6ae100b0-92d1-41be-9321-85e0933dfc42" + "urn:uuid:e8ef9653-565c-479c-8039-82d4547973c5" + "" + "" + "urn:uuid:7d418acb-07a3-4e57-984c-b8ea2f7de4ec" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:6f768ca4-c89e-4dac-9056-a29425d40ba1" + "" + "" + "" + "" + "urn:uuid:754dae53-c25f-4f3c-97e4-2bfe5463f83b" + "urn:uuid:68e3fae5-d94b-44d2-92a6-b94877fbcdb5" + "" + "" + "urn:uuid:61ce2a70-10a2-4521-850b-4218755ff3c9" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488" + "" + "" + "" + "" + "urn:uuid:d29b3884-6633-4dad-9c67-7154af342bc6" + "urn:uuid:6978c106-95bc-424b-a17c-628206a5892d" + "" + "" + "urn:uuid:001ea472-f5da-436c-86de-acaa68c1a7e4" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488" + "" + "" + "" + "" + "urn:uuid:02af22bf-f776-488a-b001-eb6e16953119" + "urn:uuid:19ff6da1-be79-4235-8d04-42201ad06e65" + "" + "" + "urn:uuid:dfa84292-0609-4097-824c-8e2e15e2ce4d" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:bd6272b6-511e-47c1-93bc-d56ebd314a70" + "" + "" + "" + "" + "" + "" + "urn:uuid:a94be493-cd55-4bf7-b496-ea87bfe38632" + "" + "" + "urn:uuid:20c6020b-1fc0-4080-bcf7-89f09f95bea8" + "urn:uuid:461f5424-8f6e-48a9-a385-5eda46fda381" + "" + "" + "urn:uuid:d1f93845-d3e5-4c3b-aa67-8d96c45cfe9c" + "36" + "" + "" + "20" + "" + "" + "" + "24" + "" + "" + "" + "" + "" + "urn:uuid:9b509f42-e4e8-4f78-8c2a-12ddd79ef3c5" + "urn:uuid:e8ef9653-565c-479c-8039-82d4547973c5" + "" + "" + "urn:uuid:a733d812-a3d7-45e9-ba50-13b856d5d35a" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:f3b263b3-096b-4360-a952-b1a9623cd0ca" + "" + "" + "" + "" + "urn:uuid:19a282e6-beac-4d99-a008-afa61378eb6c" + "urn:uuid:68e3fae5-d94b-44d2-92a6-b94877fbcdb5" + "" + "" + "urn:uuid:53de5ff9-f5f7-47c5-a2d8-117c36cce517" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535" + "" + "" + "" + "" + "urn:uuid:94b0ef77-0621-4086-95a2-85432fa97d40" + "urn:uuid:6978c106-95bc-424b-a17c-628206a5892d" + "" + "" + "urn:uuid:2ce499f2-59bc-4053-87bc-80f4b7e7b73e" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535" + "" + "" + "" + "" + "urn:uuid:9ac3b905-c599-4da8-8f0f-fc07e619899d" + "urn:uuid:19ff6da1-be79-4235-8d04-42201ad06e65" + "" + "" + "urn:uuid:0239017b-2ad9-4235-b46d-c4c1126e29fc" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:bd6272b6-511e-47c1-93bc-d56ebd314a70" + "" + "" + "" + "" + "" + "" + ""; + +const char *cpl_bad_doc = ""; + +const char *asset_map_doc = + "" + "" + "urn:uuid:68d9f591-8191-46b5-38b4-affb87a14132" + "IMF_TEST_ASSET_MAP" + "Some tool" + "1" + "2021-06-07T12:00:00+00:00" + "FFmpeg" + "" + "" + "urn:uuid:b5d674b8-c6ce-4bce-3bdf-be045dfdb2d0" + "" + "" + "IMF_TEST_ASSET_MAP_video.mxf" + "1" + "0" + "1234567" + "" + "" + "" + "" + "urn:uuid:ec3467ec-ab2a-4f49-c8cb-89caa3761f4a" + "" + "" + "IMF_TEST_ASSET_MAP_video_1.mxf" + "1" + "0" + "234567" + "" + "" + "" + "" + "urn:uuid:5cf5b5a7-8bb3-4f08-eaa6-3533d4b77fa6" + "" + "" + "IMF_TEST_ASSET_MAP_audio.mxf" + "1" + "0" + "34567" + "" + "" + "" + "" + "urn:uuid:559777d6-ec29-4375-f90d-300b0bf73686" + "" + "" + "CPL_IMF_TEST_ASSET_MAP.xml" + "1" + "0" + "12345" + "" + "" + "" + "" + "urn:uuid:dd04528d-9b80-452a-7a13-805b08278b3d" + "true" + "" + "" + "PKL_IMF_TEST_ASSET_MAP.xml" + "1" + "0" + "2345" + "" + "" + "" + "" + ""; + +static int test_cpl_parsing(void) +{ + xmlDocPtr doc; + FFIMFCPL *cpl; + int ret; + + doc = xmlReadMemory(cpl_doc, strlen(cpl_doc), NULL, NULL, 0); + if (doc == NULL) { + printf("XML parsing failed.\n"); + return 1; + } + + ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); + xmlFreeDoc(doc); + if (ret) { + printf("CPL parsing failed.\n"); + return 1; + } + + printf("%s\n", cpl->content_title_utf8); + printf(FF_IMF_UUID_FORMAT "\n", UID_ARG(cpl->id_uuid)); + printf("%i %i\n", cpl->edit_rate.num, cpl->edit_rate.den); + + printf("Marker resource count: %" PRIu32 "\n", cpl->main_markers_track->resource_count); + for (uint32_t i = 0; i < cpl->main_markers_track->resource_count; i++) { + printf("Marker resource %" PRIu32 "\n", i); + for (uint32_t j = 0; j < cpl->main_markers_track->resources[i].marker_count; j++) { + printf(" Marker %" PRIu32 "\n", j); + printf(" Label %s\n", cpl->main_markers_track->resources[i].markers[j].label_utf8); + printf(" Offset %" PRIu32 "\n", cpl->main_markers_track->resources[i].markers[j].offset); + } + } + + printf("Main image resource count: %" PRIu32 "\n", cpl->main_image_2d_track->resource_count); + for (uint32_t i = 0; i < cpl->main_image_2d_track->resource_count; i++) { + printf("Track file resource %" PRIu32 "\n", i); + printf(" " FF_IMF_UUID_FORMAT "\n", UID_ARG(cpl->main_image_2d_track->resources[i].track_file_uuid)); + } + + printf("Main audio track count: %" PRIu32 "\n", cpl->main_audio_track_count); + for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) { + printf(" Main audio virtual track %" PRIu32 "\n", i); + printf(" Main audio resource count: %" PRIu32 "\n", cpl->main_audio_tracks[i].resource_count); + for (uint32_t j = 0; j < cpl->main_audio_tracks[i].resource_count; j++) { + printf(" Track file resource %" PRIu32 "\n", j); + printf(" " FF_IMF_UUID_FORMAT "\n", UID_ARG(cpl->main_audio_tracks[i].resources[j].track_file_uuid)); + } + } + + ff_imf_cpl_free(cpl); + + return 0; +} + +static int test_bad_cpl_parsing(void) +{ + xmlDocPtr doc; + FFIMFCPL *cpl; + int ret; + + doc = xmlReadMemory(cpl_bad_doc, strlen(cpl_bad_doc), NULL, NULL, 0); + if (doc == NULL) { + printf("XML parsing failed.\n"); + return ret; + } + + ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); + xmlFreeDoc(doc); + if (ret) { + printf("CPL parsing failed.\n"); + return ret; + } + + return 0; +} + +static int check_asset_locator_attributes(IMFAssetLocator *asset, IMFAssetLocator *expected_asset) +{ + + printf("\tCompare " FF_IMF_UUID_FORMAT " to " FF_IMF_UUID_FORMAT ".\n", + UID_ARG(asset->uuid), + UID_ARG(expected_asset->uuid)); + + for (uint32_t i = 0; i < 16; ++i) { + if (asset->uuid[i] != expected_asset->uuid[i]) { + printf("Invalid asset locator UUID: found " FF_IMF_UUID_FORMAT " instead of " FF_IMF_UUID_FORMAT " expected.\n", + UID_ARG(asset->uuid), + UID_ARG(expected_asset->uuid)); + return 1; + } + } + + printf("\tCompare %s to %s.\n", asset->absolute_uri, expected_asset->absolute_uri); + if (strcmp(asset->absolute_uri, expected_asset->absolute_uri) != 0) { + printf("Invalid asset locator URI: found %s instead of %s expected.\n", + asset->absolute_uri, + expected_asset->absolute_uri); + return 1; + } + + return 0; +} + +static IMFAssetLocator ASSET_MAP_EXPECTED_LOCATORS[5] = { + {.uuid = {0xb5, 0xd6, 0x74, 0xb8, 0xc6, 0xce, 0x4b, 0xce, 0x3b, 0xdf, 0xbe, 0x04, 0x5d, 0xfd, 0xb2, 0xd0}, + .absolute_uri = (char *)"IMF_TEST_ASSET_MAP_video.mxf"}, + {.uuid = {0xec, 0x34, 0x67, 0xec, 0xab, 0x2a, 0x4f, 0x49, 0xc8, 0xcb, 0x89, 0xca, 0xa3, 0x76, 0x1f, 0x4a}, + .absolute_uri = (char *)"IMF_TEST_ASSET_MAP_video_1.mxf"}, + {.uuid = {0x5c, 0xf5, 0xb5, 0xa7, 0x8b, 0xb3, 0x4f, 0x08, 0xea, 0xa6, 0x35, 0x33, 0xd4, 0xb7, 0x7f, 0xa6}, + .absolute_uri = (char *)"IMF_TEST_ASSET_MAP_audio.mxf"}, + {.uuid = {0x55, 0x97, 0x77, 0xd6, 0xec, 0x29, 0x43, 0x75, 0xf9, 0x0d, 0x30, 0x0b, 0x0b, 0xf7, 0x36, 0x86}, + .absolute_uri = (char *)"CPL_IMF_TEST_ASSET_MAP.xml"}, + {.uuid = {0xdd, 0x04, 0x52, 0x8d, 0x9b, 0x80, 0x45, 0x2a, 0x7a, 0x13, 0x80, 0x5b, 0x08, 0x27, 0x8b, 0x3d}, + .absolute_uri = (char *)"PKL_IMF_TEST_ASSET_MAP.xml"}, +}; + +static int test_asset_map_parsing(void) +{ + IMFAssetLocatorMap asset_locator_map; + xmlDoc *doc; + int ret; + + doc = xmlReadMemory(asset_map_doc, strlen(asset_map_doc), NULL, NULL, 0); + if (doc == NULL) { + printf("Asset map XML parsing failed.\n"); + return 1; + } + + printf("Allocate asset map\n"); + imf_asset_locator_map_init(&asset_locator_map); + + printf("Parse asset map XML document\n"); + ret = parse_imf_asset_map_from_xml_dom(NULL, doc, &asset_locator_map, doc->name); + if (ret) { + printf("Asset map parsing failed.\n"); + goto cleanup; + } + + printf("Compare assets count: %d to 5\n", asset_locator_map.asset_count); + if (asset_locator_map.asset_count != 5) { + printf("Asset map parsing failed: found %d assets instead of 5 expected.\n", + asset_locator_map.asset_count); + ret = 1; + goto cleanup; + } + + for (uint32_t i = 0; i < asset_locator_map.asset_count; ++i) { + printf("For asset: %d:\n", i); + ret = check_asset_locator_attributes(&(asset_locator_map.assets[i]), + &(ASSET_MAP_EXPECTED_LOCATORS[i])); + if (ret > 0) + goto cleanup; + } + +cleanup: + imf_asset_locator_map_deinit(&asset_locator_map); + xmlFreeDoc(doc); + return ret; +} + +typedef struct PathTypeTestStruct { + const char *path; + int is_url; + int is_unix_absolute_path; + int is_dos_absolute_path; +} PathTypeTestStruct; + +static const PathTypeTestStruct PATH_TYPE_TEST_STRUCTS[11] = { + {.path = "file://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "http://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "https://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "s3://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "ftp://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "/path/to/somewhere", .is_url = 0, .is_unix_absolute_path = 1, .is_dos_absolute_path = 0}, + {.path = "path/to/somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "C:\\path\\to\\somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 1}, + {.path = "C:/path/to/somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 1}, + {.path = "\\\\path\\to\\somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 1}, + {.path = "path\\to\\somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, +}; + +static int test_path_type_functions(void) +{ + PathTypeTestStruct path_type; + for (uint32_t i = 0; i < 11; ++i) { + path_type = PATH_TYPE_TEST_STRUCTS[i]; + if (imf_uri_is_url(path_type.path) != path_type.is_url) { + fprintf(stderr, + "URL comparison test failed for '%s', got %d instead of expected %d\n", + path_type.path, + path_type.is_url, + !path_type.is_url); + goto fail; + } + + if (imf_uri_is_unix_abs_path(path_type.path) != path_type.is_unix_absolute_path) { + fprintf(stderr, + "Unix absolute path comparison test failed for '%s', got %d instead of expected %d\n", + path_type.path, + path_type.is_unix_absolute_path, + !path_type.is_unix_absolute_path); + goto fail; + } + + if (imf_uri_is_dos_abs_path(path_type.path) != path_type.is_dos_absolute_path) { + fprintf(stderr, + "DOS absolute path comparison test failed for '%s', got %d instead of expected %d\n", + path_type.path, + path_type.is_dos_absolute_path, + !path_type.is_dos_absolute_path); + goto fail; + } + } + + return 0; + +fail: + return 1; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + if (test_cpl_parsing() != 0) + ret = 1; + + if (test_asset_map_parsing() != 0) + ret = 1; + + if (test_path_type_functions() != 0) + ret = 1; + + printf("#### The following should fail ####\n"); + if (test_bad_cpl_parsing() == 0) + ret = 1; + printf("#### End failing test ####\n"); + + return ret; +} diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak index d1e81284ed..59ff0ebc8d 100644 --- a/tests/fate/libavformat.mak +++ b/tests/fate/libavformat.mak @@ -22,6 +22,10 @@ FATE_LIBAVFORMAT-$(CONFIG_MOV_MUXER) += fate-movenc fate-movenc: libavformat/tests/movenc$(EXESUF) fate-movenc: CMD = run libavformat/tests/movenc$(EXESUF) +FATE_LIBAVFORMAT-$(CONFIG_IMF_DEMUXER) += fate-imf +fate-imf: libavformat/tests/imf$(EXESUF) +fate-imf: CMD = run libavformat/tests/imf$(EXESUF) + FATE_LIBAVFORMAT += $(FATE_LIBAVFORMAT-yes) FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT) fate-libavformat: $(FATE_LIBAVFORMAT) diff --git a/tests/ref/fate/imf b/tests/ref/fate/imf new file mode 100644 index 0000000000..90b461dc5d --- /dev/null +++ b/tests/ref/fate/imf @@ -0,0 +1,54 @@ +FFMPEG sample content +urn:uuid:8713c020-2489-45f5-a9f7-87be539e20b5 +24000 1001 +Marker resource count: 2 +Marker resource 0 + Marker 0 + Label LFOA + Offset 5 +Marker resource 1 + Marker 0 + Label FFOA + Offset 20 + Marker 1 + Label LFOC + Offset 24 +Main image resource count: 2 +Track file resource 0 + urn:uuid:6f768ca4-c89e-4dac-9056-a29425d40ba1 +Track file resource 1 + urn:uuid:f3b263b3-096b-4360-a952-b1a9623cd0ca +Main audio track count: 2 + Main audio virtual track 0 + Main audio resource count: 2 + Track file resource 0 + urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488 + Track file resource 1 + urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535 + Main audio virtual track 1 + Main audio resource count: 2 + Track file resource 0 + urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488 + Track file resource 1 + urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535 +Allocate asset map +Parse asset map XML document +Compare assets count: 5 to 5 +For asset: 0: + Compare urn:uuid:b5d674b8-c6ce-4bce-3bdf-be045dfdb2d0 to urn:uuid:b5d674b8-c6ce-4bce-3bdf-be045dfdb2d0. + Compare IMF_TEST_ASSET_MAP_video.mxf to IMF_TEST_ASSET_MAP_video.mxf. +For asset: 1: + Compare urn:uuid:ec3467ec-ab2a-4f49-c8cb-89caa3761f4a to urn:uuid:ec3467ec-ab2a-4f49-c8cb-89caa3761f4a. + Compare IMF_TEST_ASSET_MAP_video_1.mxf to IMF_TEST_ASSET_MAP_video_1.mxf. +For asset: 2: + Compare urn:uuid:5cf5b5a7-8bb3-4f08-eaa6-3533d4b77fa6 to urn:uuid:5cf5b5a7-8bb3-4f08-eaa6-3533d4b77fa6. + Compare IMF_TEST_ASSET_MAP_audio.mxf to IMF_TEST_ASSET_MAP_audio.mxf. +For asset: 3: + Compare urn:uuid:559777d6-ec29-4375-f90d-300b0bf73686 to urn:uuid:559777d6-ec29-4375-f90d-300b0bf73686. + Compare CPL_IMF_TEST_ASSET_MAP.xml to CPL_IMF_TEST_ASSET_MAP.xml. +For asset: 4: + Compare urn:uuid:dd04528d-9b80-452a-7a13-805b08278b3d to urn:uuid:dd04528d-9b80-452a-7a13-805b08278b3d. + Compare PKL_IMF_TEST_ASSET_MAP.xml to PKL_IMF_TEST_ASSET_MAP.xml. +#### The following should fail #### +CPL parsing failed. +#### End failing test #### From 9cfc7a244052dced520776ff0ecc6f0a9390f62b Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sat, 27 Nov 2021 15:21:12 +0530 Subject: [PATCH 656/894] avformat/mov: add option max_stts_delta Very high stts sample deltas may occasionally be intended but usually they are written in error or used to store a negative value for dts correction when treated as signed 32-bit integers. This option lets the user set an upper limit, beyond which the delta is clamped to 1. Values greater than the limit if negative when cast to int32 are used to adjust onward dts. Unit is the track time scale. Default is UINT_MAX - 48000*10 which allows upto a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of uint32 range. Signed-off-by: Gyan Doshi Reviewed-by: Michael Niedermayer --- doc/demuxers.texi | 9 ++++++++ libavformat/isom.h | 1 + libavformat/mov.c | 55 +++++++++++++++++++++++++--------------------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index b474a24278..26ae768d7a 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -726,6 +726,15 @@ specify. @item decryption_key 16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7). + +@item max_stts_delta +Very high sample deltas written in a trak's stts box may occasionally be intended but usually they are written in +error or used to store a negative value for dts correction when treated as signed 32-bit integers. This option lets +the user set an upper limit, beyond which the delta is clamped to 1. Values greater than the limit if negative when +cast to int32 are used to adjust onward dts. + +Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows upto +a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range. @end table @subsection Audible AAX diff --git a/libavformat/isom.h b/libavformat/isom.h index ef8f19b18c..625dea8421 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -305,6 +305,7 @@ typedef struct MOVContext { int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd int have_read_mfra_size; uint32_t mfra_size; + uint32_t max_stts_delta; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff --git a/libavformat/mov.c b/libavformat/mov.c index 2aed6e80ef..351ecde770 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2925,6 +2925,8 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) unsigned int i, entries, alloc_size = 0; int64_t duration = 0; int64_t total_sample_count = 0; + int64_t current_dts = 0; + int64_t corrected_dts = 0; if (c->fc->nb_streams < 1) return 0; @@ -2965,11 +2967,34 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->stts_data[i].count= sample_count; sc->stts_data[i].duration= sample_duration; - av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n", + av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n", sample_count, sample_duration); - duration+=(int64_t)sample_duration*(uint64_t)sample_count; - total_sample_count+=sample_count; + /* STTS sample offsets are uint32 but some files store it as int32 + * with negative values used to correct DTS delays. + There may be abnormally large values as well. */ + if (sample_duration > c->max_stts_delta) { + // assume high delta is a correction if negative when cast as int32 + int32_t delta_magnitude = (int32_t)sample_duration; + av_log(c->fc, AV_LOG_WARNING, "Too large sample offset %u in stts entry %u with count %u in st:%d. Clipping to 1.\n", + sample_duration, i, sample_count, st->index); + sc->stts_data[i].duration = 1; + corrected_dts += (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count; + } else { + corrected_dts += sample_duration * sample_count; + } + + current_dts += sc->stts_data[i].duration * sample_count; + + if (current_dts > corrected_dts) { + int64_t drift = (current_dts - corrected_dts)/FFMAX(sample_count, 1); + uint32_t correction = (sc->stts_data[i].duration > drift) ? drift : sc->stts_data[i].duration - 1; + current_dts -= correction * sample_count; + sc->stts_data[i].duration -= correction; + } + + duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count; + total_sample_count+=sc->stts_data[i].count; } sc->stts_count = i; @@ -3856,13 +3881,10 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int distance = 0; unsigned int rap_group_index = 0; unsigned int rap_group_sample = 0; - int64_t last_dts = 0; - int64_t dts_correction = 0; int rap_group_present = sc->rap_group_count && sc->rap_group; int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0); current_dts -= sc->dts_shift; - last_dts = current_dts; if (!sc->sample_count || sti->nb_index_entries) return; @@ -3973,26 +3995,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) current_offset += sample_size; stream_size += sample_size; - /* A negative sample duration is invalid based on the spec, - * but some samples need it to correct the DTS. */ - if (sc->stts_data[stts_index].duration < 0) { - av_log(mov->fc, AV_LOG_WARNING, - "Invalid SampleDelta %d in STTS, at %d st:%d\n", - sc->stts_data[stts_index].duration, stts_index, - st->index); - dts_correction += sc->stts_data[stts_index].duration - 1; - sc->stts_data[stts_index].duration = 1; - } current_dts += sc->stts_data[stts_index].duration; - if (!dts_correction || current_dts + dts_correction > last_dts) { - current_dts += dts_correction; - dts_correction = 0; - } else { - /* Avoid creating non-monotonous DTS */ - dts_correction += current_dts - last_dts - 1; - current_dts = last_dts + 1; - } - last_dts = current_dts; + distance++; stts_sample++; current_sample++; @@ -8577,6 +8581,7 @@ static const AVOption mov_options[] = { { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "max_stts_delta", "treat offsets above this value as invalid", OFFSET(max_stts_delta), AV_OPT_TYPE_INT, {.i64 = UINT_MAX-48000*10 }, 0, UINT_MAX, .flags = AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; From 2f6360ff21a98f9db6af3e0932d39f1dc7b47d6c Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sat, 1 Jan 2022 00:29:41 +0530 Subject: [PATCH 657/894] configure: bump year --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 07fb7925d8..6ad70b9f7b 100755 --- a/configure +++ b/configure @@ -7754,7 +7754,7 @@ cat > $TMPH < Date: Mon, 27 Dec 2021 11:20:24 +0200 Subject: [PATCH 658/894] http: make caching of redirect url optional added "cache_redirect" option to http. when enabled, requests issued after seek will use the latest redirected url. when disabled, each call to seek will revert to the original url that was sent to http_open. currently, the default remains 'enabled', until the next major libavformat bump, where it will change to 'disabled'. --- libavformat/http.c | 27 +++++++++++++++++++++++++++ libavformat/version.h | 1 + 2 files changed, 28 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 91650be47a..4415a26f2c 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -69,7 +69,9 @@ typedef struct HTTPContext { uint64_t chunksize; int chunkend; uint64_t off, end_off, filesize; + char *uri; char *location; + int cache_redirect; HTTPAuthState auth_state; HTTPAuthState proxy_auth_state; char *http_proxy; @@ -169,6 +171,7 @@ static const AVOption options[] = { { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E}, { "short_seek_size", "Threshold to favor readahead over seek.", OFFSET(short_seek_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, + { "cache_redirect", "Save redirected URL for subsequent seek operations", OFFSET(cache_redirect), AV_OPT_TYPE_BOOL, { .i64 = FF_HTTP_CACHE_REDIRECT_DEFAULT }, 0, 1, D }, { NULL } }; @@ -432,11 +435,17 @@ int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **opts) s->chunkend = 0; s->off = 0; s->icy_data_read = 0; + av_free(s->location); s->location = av_strdup(uri); if (!s->location) return AVERROR(ENOMEM); + av_free(s->uri); + s->uri = av_strdup(uri); + if (!s->uri) + return AVERROR(ENOMEM); + if ((ret = av_opt_set_dict(s, opts)) < 0) return ret; @@ -623,9 +632,15 @@ static int http_open(URLContext *h, const char *uri, int flags, h->is_streamed = 1; s->filesize = UINT64_MAX; + s->location = av_strdup(uri); if (!s->location) return AVERROR(ENOMEM); + + s->uri = av_strdup(uri); + if (!s->uri) + return AVERROR(ENOMEM); + if (options) av_dict_copy(&s->chained_options, *options, 0); @@ -651,6 +666,7 @@ bail_out: if (ret < 0) { av_dict_free(&s->chained_options); av_dict_free(&s->cookie_dict); + av_freep(&s->uri); } return ret; } @@ -1769,6 +1785,7 @@ static int http_close(URLContext *h) ffurl_closep(&s->hd); av_dict_free(&s->chained_options); av_dict_free(&s->cookie_dict); + av_freep(&s->uri); return ret; } @@ -1810,6 +1827,16 @@ static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int fo return s->off; } + /* if redirect caching is disabled, revert to the original uri */ + if (!s->cache_redirect && strcmp(s->uri, s->location)) { + char *new_uri; + new_uri = av_strdup(s->uri); + if (!new_uri) + return AVERROR(ENOMEM); + av_free(s->location); + s->location = new_uri; + } + /* we save the old context in case the seek fails */ old_buf_size = s->buf_end - s->buf_ptr; memcpy(old_buf, s->buf_ptr, old_buf_size); diff --git a/libavformat/version.h b/libavformat/version.h index 917b9ffa5d..f372380dcf 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -60,6 +60,7 @@ #define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_HLS_TS_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) +#define FF_HTTP_CACHE_REDIRECT_DEFAULT (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_R_FRAME_RATE 1 From 0154f142f3d09e1ab2b1421bb77ec9ca91a9d82f Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 31 Dec 2021 19:21:35 -0300 Subject: [PATCH 659/894] avformat/Makefile: add imf.h to SKIPHEADERS Should fix "make checkheaders". Signed-off-by: James Almer --- libavformat/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index 10d1a89083..e31b248ac0 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -685,6 +685,7 @@ OBJS-$(CONFIG_IEC61883_INDEV) += dv.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avformatres.o +SKIPHEADERS-$(CONFIG_IMF_DEMUXER) += imf.h SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h From c41761676276968b9f2f33c5c62357cde3a51dbc Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 27 Aug 2021 15:13:42 +0800 Subject: [PATCH 660/894] lavc/{av1, h264, h265}_metadata_bsf: fix description of tick_rate Users may take the description literally which leads to inverted results. Signed-off-by: Zhao Zhili Reviewed-by: Jun Zhao Date: Sun, 26 Dec 2021 11:18:51 +0100 Subject: [PATCH 661/894] avcodec/speexdec: Consider mode in frame size check No speex samples with non default frame sizes are known (to me) the official speexenc seems to only generate the 3 default ones. Thus it may be that the fuzzer samples where the first non default values encountered by the decoder. Possibly the "<" should be "!=" Fixes: out of array access Fixes: 42821/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SPEEX_fuzzer-5640695772217344 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/speexdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c index 1c33607db2..dcbdf5e010 100644 --- a/libavcodec/speexdec.c +++ b/libavcodec/speexdec.c @@ -1419,7 +1419,7 @@ static int parse_speex_extradata(AVCodecContext *avctx, return AVERROR_INVALIDDATA; s->bitrate = bytestream_get_le32(&buf); s->frame_size = bytestream_get_le32(&buf); - if (s->frame_size < NB_FRAME_SIZE) + if (s->frame_size < NB_FRAME_SIZE << s->mode) return AVERROR_INVALIDDATA; s->vbr = bytestream_get_le32(&buf); s->frames_per_packet = bytestream_get_le32(&buf); From b84ce56589755ec290b8564a5d69c5cb1b2adec6 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 2 Jan 2022 23:57:41 +0100 Subject: [PATCH 662/894] hwcontext_vulkan: remove VK_EXT_hdr_metadata from autoloaded extensions list We don't use it. Was copied from libplacebo's recommended defaults. Creates problems with validation on Intel devices, where the driver still advertizes it, even though it's not usable without a swapchain. --- libavutil/hwcontext_vulkan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 83a7527198..e90edea111 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -341,7 +341,6 @@ static const VulkanOptExtension optional_instance_exts[] = { static const VulkanOptExtension optional_device_exts[] = { /* Misc or required by other extensions */ { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, - { VK_EXT_HDR_METADATA_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, From c7c37a8f226cd6ed699c242358d0441faabc80f9 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Sun, 2 Jan 2022 22:51:39 +0800 Subject: [PATCH 663/894] transpose_vulkan: add passthrough option The following command is on how to apply passthrough option: ffmpeg -init_hw_device vulkan -i input.264 -vf hwupload=extra_hw_frames=16,transpose_vulkan=passthrough=landscape,hwdownload,format=yuv420p output.264 Signed-off-by: Wu Jianhua --- libavfilter/vf_transpose_vulkan.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c index ce83cf0fd7..30d052e08c 100644 --- a/libavfilter/vf_transpose_vulkan.c +++ b/libavfilter/vf_transpose_vulkan.c @@ -35,6 +35,7 @@ typedef struct TransposeVulkanContext { VkDescriptorImageInfo output_images[3]; int dir; + int passthrough; int initialized; } TransposeVulkanContext; @@ -222,6 +223,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) TransposeVulkanContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + if (s->passthrough) + return ff_filter_frame(outlink, in); + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { err = AVERROR(ENOMEM); @@ -267,6 +271,17 @@ static int config_props_output(AVFilterLink *outlink) FFVulkanContext *vkctx = &s->vkctx; AVFilterLink *inlink = avctx->inputs[0]; + if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) || + (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) { + av_log(avctx, AV_LOG_VERBOSE, + "w:%d h:%d -> w:%d h:%d (passthrough mode)\n", + inlink->w, inlink->h, inlink->w, inlink->h); + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + return outlink->hw_frames_ctx ? 0 : AVERROR(ENOMEM); + } else { + s->passthrough = TRANSPOSE_PT_TYPE_NONE; + } + vkctx->output_width = inlink->h; vkctx->output_height = inlink->w; @@ -288,6 +303,13 @@ static const AVOption transpose_vulkan_options[] = { { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "dir" }, { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "dir" }, { "clock_flip", "rotate clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, + + { "passthrough", "do not apply transposition if the input matches the specified geometry", + OFFSET(passthrough), AV_OPT_TYPE_INT, {.i64=TRANSPOSE_PT_TYPE_NONE}, 0, INT_MAX, FLAGS, "passthrough" }, + { "none", "always apply transposition", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_NONE}, INT_MIN, INT_MAX, FLAGS, "passthrough" }, + { "portrait", "preserve portrait geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_PORTRAIT}, INT_MIN, INT_MAX, FLAGS, "passthrough" }, + { "landscape", "preserve landscape geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_LANDSCAPE}, INT_MIN, INT_MAX, FLAGS, "passthrough" }, + { NULL } }; From 68d0a7e446e0620e7eb9c8e1d93c4ed42f8c8a0a Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Sun, 2 Jan 2022 22:51:40 +0800 Subject: [PATCH 664/894] avfilter/vf_scale_vulkan: align struct ScaleVulkanContext On 64 bit Operating System, sizeof(ScaleVulkanContext): reduce from 2400 to 2392 on Linux reduce from 2416 to 2408 on Windows Signed-off-by: Wu Jianhua --- libavfilter/vf_scale_vulkan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index cfce5ab1f8..c87a8d7e2e 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -35,7 +35,6 @@ enum ScalerFunc { typedef struct ScaleVulkanContext { FFVulkanContext vkctx; - int initialized; FFVkQueueFamilyCtx qf; FFVkExecContext *exec; FFVulkanPipeline *pl; @@ -46,11 +45,14 @@ typedef struct ScaleVulkanContext { VkDescriptorImageInfo output_images[3]; VkDescriptorBufferInfo params_desc; - enum ScalerFunc scaler; char *out_format_string; - enum AVColorRange out_range; char *w_expr; char *h_expr; + + enum ScalerFunc scaler; + enum AVColorRange out_range; + + int initialized; } ScaleVulkanContext; static const char scale_bilinear[] = { From a670cad2c43de442afeeefde0fb57d74b1a03acb Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 31 Dec 2021 14:15:29 -0300 Subject: [PATCH 665/894] fate/libswcale: add missing samples dependency to sws-slice tests Signed-off-by: James Almer --- tests/fate/libswscale.mak | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/fate/libswscale.mak b/tests/fate/libswscale.mak index 599d27b0a5..cf9319ec44 100644 --- a/tests/fate/libswscale.mak +++ b/tests/fate/libswscale.mak @@ -15,8 +15,10 @@ fate-sws-slice-bgr0-nv12: CMD = run tools/scale_slice_test$(EXESUF) $(TARGET_SAM fate-sws-slice: $(SWS_SLICE_TEST-yes) $(SWS_SLICE_TEST-yes): tools/scale_slice_test$(EXESUF) $(SWS_SLICE_TEST-yes): REF = /dev/null -FATE_LIBSWSCALE += $(SWS_SLICE_TEST-yes) +FATE_LIBSWSCALE_SAMPLES += $(SWS_SLICE_TEST-yes) FATE_LIBSWSCALE += $(FATE_LIBSWSCALE-yes) +FATE_LIBSWSCALE_SAMPLES += $(FATE_LIBSWSCALE_SAMPLES-yes) FATE-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE) -fate-libswscale: $(FATE_LIBSWSCALE) +FATE_EXTERN-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE_SAMPLES) +fate-libswscale: $(FATE_LIBSWSCALE) $(FATE_LIBSWSCALE_SAMPLES) From 064ab95cc78249c95d0257db249483bb38b59829 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 3 Jan 2022 07:12:45 +0100 Subject: [PATCH 666/894] configure: Make IMF demuxer require MXF demuxer The former is useless without the latter. Reviewed-by: Zane van Iperen Signed-off-by: Andreas Rheinhardt --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 6ad70b9f7b..e2ea473565 100755 --- a/configure +++ b/configure @@ -3416,6 +3416,7 @@ hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" imf_demuxer_deps="libxml2" +imf_demuxer_select="mxf_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" From 5e2a1f1e7db630d547e89988414499ea788bd68e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 15 Dec 2021 10:17:02 +0800 Subject: [PATCH 667/894] libavcodec/pthread_frame: remove duplicate pointers '*src' and '*avctx' point to the same memory. It is enough to keep one of them. Signed-off-by: Yu Yang Signed-off-by: Anton Khirnov --- libavcodec/pthread_frame.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 73b1b7d7d9..85a6bc98c1 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -765,14 +765,14 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, FrameThreadContext *fctx, AVCodecContext *avctx, - AVCodecContext *src, const AVCodec *codec, int first) + const AVCodec *codec, int first) { AVCodecContext *copy; int err; atomic_init(&p->state, STATE_INPUT_READY); - copy = av_memdup(src, sizeof(*src)); + copy = av_memdup(avctx, sizeof(*avctx)); if (!copy) return AVERROR(ENOMEM); copy->priv_data = NULL; @@ -784,7 +784,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, p->parent = fctx; p->avctx = copy; - copy->internal = av_memdup(src->internal, sizeof(*src->internal)); + copy->internal = av_memdup(avctx->internal, sizeof(*avctx->internal)); if (!copy->internal) return AVERROR(ENOMEM); copy->internal->thread_ctx = p; @@ -798,7 +798,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, if (codec->priv_class) { *(const AVClass **)copy->priv_data = codec->priv_class; - err = av_opt_copy(copy->priv_data, src->priv_data); + err = av_opt_copy(copy->priv_data, avctx->priv_data); if (err < 0) return err; } @@ -843,7 +843,6 @@ int ff_frame_thread_init(AVCodecContext *avctx) { int thread_count = avctx->thread_count; const AVCodec *codec = avctx->codec; - AVCodecContext *src = avctx; FrameThreadContext *fctx; int err, i = 0; @@ -876,7 +875,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) fctx->delaying = 1; if (codec->type == AVMEDIA_TYPE_VIDEO) - avctx->delay = src->thread_count - 1; + avctx->delay = avctx->thread_count - 1; fctx->threads = av_calloc(thread_count, sizeof(*fctx->threads)); if (!fctx->threads) { @@ -888,7 +887,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) PerThreadContext *p = &fctx->threads[i]; int first = !i; - err = init_thread(p, &i, fctx, avctx, src, codec, first); + err = init_thread(p, &i, fctx, avctx, codec, first); if (err < 0) goto error; } From be97d2a825a12c9c01a61b985d44eb7424628fd6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 2 Jan 2022 18:38:02 +0100 Subject: [PATCH 668/894] lavf: add a flag for experimental (de)muxers --- doc/APIchanges | 3 +++ libavformat/avformat.h | 7 +++++++ libavformat/format.c | 2 ++ libavformat/version.h | 2 +- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 670a59329e..29c235630e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2022-01-xx - xxxxxxxxxx - lavf 59.13.100 - avformat.h + Add AVFMT_EXPERIMENTAL flag. + 2021-12-xx - xxxxxxxxxx - lavu 57.13.100 - hwcontext_videotoolbox.h Add av_vt_pixbuf_set_attachments diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 70b36d7682..6ce367e854 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -463,6 +463,13 @@ typedef struct AVProbeData { /// Demuxer will use avio_open, no opened file should be provided by the caller. #define AVFMT_NOFILE 0x0001 #define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +/** + * The muxer/demuxer is experimental and should be used with caution. + * + * - demuxers: will not be selected automatically by probing, must be specified + * explicitly. + */ +#define AVFMT_EXPERIMENTAL 0x0004 #define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ #define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ #define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ diff --git a/libavformat/format.c b/libavformat/format.c index 387627009e..52b85c16a2 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -158,6 +158,8 @@ const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, } while ((fmt1 = av_demuxer_iterate(&i))) { + if (fmt1->flags & AVFMT_EXPERIMENTAL) + continue; if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2")) continue; score = 0; diff --git a/libavformat/version.h b/libavformat/version.h index f372380dcf..79eb22c230 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 12 +#define LIBAVFORMAT_VERSION_MINOR 13 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 70f318e6b6c1551dff4d8571b8158f9d1cf05827 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 2 Jan 2022 18:40:09 +0100 Subject: [PATCH 669/894] lavf/imfdec: mark as experimental People have expressed concerns about its safety, so prevent it from being auto-selected without explicit user indication. --- libavformat/imfdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index f17064cfcd..228ba494ae 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -889,6 +889,7 @@ static const AVClass imf_class = { const AVInputFormat ff_imf_demuxer = { .name = "imf", .long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"), + .flags = AVFMT_EXPERIMENTAL, .flags_internal = FF_FMT_INIT_CLEANUP, .priv_class = &imf_class, .priv_data_size = sizeof(IMFContext), From be91c89bab427fdd334dcd5242d33ccaefa823d7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 3 Jan 2022 20:28:17 +0100 Subject: [PATCH 670/894] doc/APIchanges: Fill in missing things Reviewed-by: James Almer Signed-off-by: Michael Niedermayer --- doc/APIchanges | 74 +++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 29c235630e..50b5f0bb53 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,85 +14,85 @@ libavutil: 2021-04-27 API changes, most recent first: -2022-01-xx - xxxxxxxxxx - lavf 59.13.100 - avformat.h +2022-01-03 - 70f318e6b6c - lavf 59.13.100 - avformat.h Add AVFMT_EXPERIMENTAL flag. -2021-12-xx - xxxxxxxxxx - lavu 57.13.100 - hwcontext_videotoolbox.h +2021-12-22 - b7e1ec7bda9 - lavu 57.13.100 - hwcontext_videotoolbox.h Add av_vt_pixbuf_set_attachments -2021-12-xx - xxxxxxxxxx - lavu 57.13.100 - hwcontext_videotoolbox.h +2021-12-22 - 69bd95dcd8d - lavu 57.13.100 - hwcontext_videotoolbox.h Add av_map_videotoolbox_chroma_loc_from_av Add av_map_videotoolbox_color_matrix_from_av Add av_map_videotoolbox_color_primaries_from_av Add av_map_videotoolbox_color_trc_from_av -2021-12-21 - xxxxxxxxxx - lavu 57.12.100 - cpu.h +2021-12-21 - ffbab99f2c2 - lavu 57.12.100 - cpu.h Add AV_CPU_FLAG_SLOW_GATHER. -2021-12-20 - xxxxxxxxxx - lavu 57.11.101 - display.h +2021-12-20 - 278068dc60d - lavu 57.11.101 - display.h Modified the documentation of av_display_rotation_set() to match its longstanding actual behaviour of treating the angle as directed clockwise. -2021-12-xx - xxxxxxxxxx - lavf 59.10.100 - avformat.h +2021-12-12 - 64834bb86a1 - lavf 59.10.100 - avformat.h Add AVFormatContext io_close2 which returns an int -2021-11-10 - xxxxxxxxxx - lavu 57.11.100 - hwcontext_vulkan.h +2021-12-10 - f45cbb775e4 - lavu 57.11.100 - hwcontext_vulkan.h Add AVVkFrame.offset and AVVulkanFramesContext.flags. -2021-11-xx - xxxxxxxxxx - lavfi 8.19.100 - avfilter.h +2021-12-04 - b9c928a486f - lavfi 8.19.100 - avfilter.h Add AVFILTER_FLAG_METADATA_ONLY. -2021-12-03 - xxxxxxxxxx - lavu 57.10.100 - frame.h +2021-12-03 - b236ef0a594 - lavu 57.10.100 - frame.h Add AVFrame.time_base -2021-11-22 - xxxxxxxxxx - lavu 57.9.100 - pixfmt.h +2021-11-22 - b2cd1fb2ec6 - lavu 57.9.100 - pixfmt.h Add AV_PIX_FMT_P210, AV_PIX_FMT_P410, AV_PIX_FMT_P216, and AV_PIX_FMT_P416. -2021-11-17 - xxxxxxxxxx - lavf 57.9.100 - frame.h +2021-11-17 - 54e65aa38ab - lavf 57.9.100 - frame.h Add AV_FRAME_DATA_DOVI_RPU_BUFFER. -2021-11-xx - xxxxxxxxxx - lavf 59.9.100 - avformat.h +2021-11-16 - ed75a08d36c - lavf 59.9.100 - avformat.h Add av_stream_get_class(). Schedule adding AVStream.av_class at libavformat major version 60. Add av_disposition_to_string() and av_disposition_from_string(). Add "disposition" AVOption to AVStream's class. -2021-11-12 - xxxxxxxxxx - lavu 57.8.100 - hwcontext_vulkan.h +2021-11-12 - 8478d60d5b5 - lavu 57.8.100 - hwcontext_vulkan.h Added AVVkFrame.sem_value, AVVulkanDeviceContext.queue_family_encode_index, nb_encode_queues, queue_family_decode_index, and nb_decode_queues. -2021-10-18 - xxxxxxxxxx - lavf 59.8.100 - avio.h +2021-10-18 - 682bafdb125 - lavf 59.8.100 - avio.h Introduce public bytes_{read,written} statistic fields to AVIOContext. -2021-10-13 - xxxxxxxxxx - lavf 59.7.100 - avio.h +2021-10-13 - a5622ed16f8 - lavf 59.7.100 - avio.h Deprecate AVIOContext.written. Originally added as a private entry in commit 3f75e5116b900f1428aa13041fc7d6301bf1988a, its grouping with the comment noting its private state was missed during merging of the field from Libav (most likely due to an already existing field in between). -2021-09-21 - xxxxxxxxxx - lavu 57.7.100 - pixfmt.h +2021-09-21 - 0760d9153c3 - lavu 57.7.100 - pixfmt.h Add AV_PIX_FMT_X2BGR10. -2021-09-20 - xxxxxxxxxx - lavu 57.6.100 - mem.h +2021-09-20 - 8d5de914d31 - lavu 57.6.100 - mem.h Deprecate av_mallocz_array() as it is identical to av_calloc(). -2021-09-20 - xxxxxxxxxx - lavc 59.9.100 - avcodec.h +2021-09-20 - 176b8d785bf - lavc 59.9.100 - avcodec.h Deprecate AVCodecContext.sub_text_format and the corresponding AVOptions. It is unused since the last major bump. -2021-09-20 - xxxxxxxxxx - lavc 59.8.100 - avcodec.h codec.h +2021-09-20 - dd846bc4a91 - lavc 59.8.100 - avcodec.h codec.h Deprecate AV_CODEC_FLAG_TRUNCATED and AV_CODEC_CAP_TRUNCATED, as they are redundant with parsers. -2021-09-17 - xxxxxxxxxx - lavu 57.5.101 - buffer.h +2021-09-17 - ccfdef79b13 - lavu 57.5.101 - buffer.h Constified the input parameters in av_buffer_replace(), av_buffer_ref(), and av_buffer_pool_buffer_get_opaque(). -2021-09-08 - xxxxxxxxxx - lavu 57.5.100 - hwcontext_d3d11va.h +2021-09-08 - 4f78711f9c2 - lavu 57.5.100 - hwcontext_d3d11va.h Add AVD3D11VAFramesContext.texture_infos -2021-09-06 - xxxxxxxxxx - lsws 6.1.100 - swscale.h +2021-09-06 - 42cd64c1826 - lsws 6.1.100 - swscale.h Add AVFrame-based scaling API: - sws_scale_frame() - sws_frame_start() @@ -101,54 +101,54 @@ API changes, most recent first: - sws_receive_slice() - sws_receive_slice_alignment() -2021-09-02 - xxxxxxxxxx - lavc 59.7.100 - avcodec.h +2021-09-02 - cbf111059d2 - lavc 59.7.100 - avcodec.h Incremented the number of elements of AVCodecParser.codec_ids to seven. -2021-08-24 - xxxxxxxxxx - lavc 59.6.100 - avcodec.h +2021-08-24 - 590a7e02f04 - lavc 59.6.100 - avcodec.h Add FF_CODEC_PROPERTY_FILM_GRAIN -2021-08-20 - xxxxxxxxxx - lavfi 8.3.100 - avfilter.H +2021-08-20 - 7c5f998196d - lavfi 8.3.100 - avfilter.H Add avfilter_filter_pad_count() as a replacement for avfilter_pad_count(). Deprecate avfilter_pad_count(). -2021-08-17 - xxxxxxxxxx - lavu 57.4.101 - opt.h +2021-08-17 - 8c53b145993 - lavu 57.4.101 - opt.h av_opt_copy() now guarantees that allocated src and dst options don't alias each other even on error. -2021-08-14 - xxxxxxxxxx - lavu 57.4.100 - imgutils.h +2021-08-14 - d5de9965ef6 - lavu 57.4.100 - imgutils.h Add av_image_copy_plane_uc_from() -2021-08-02 - xxxxxxxxxx - lavc 59.4.100 - packet.h +2021-08-02 - a1a0fddfd05 - lavc 59.4.100 - packet.h Add AVPacket.opaque, AVPacket.opaque_ref, AVPacket.time_base. -2021-07-23 - xxxxxxxxxx - lavu 57.3.100 - common.h macros.h +2021-07-23 - 2dd8acbe800 - lavu 57.3.100 - common.h macros.h Move several macros (AV_NE, FFDIFFSIGN, FFMAX, FFMAX3, FFMIN, FFMIN3, FFSWAP, FF_ARRAY_ELEMS, MKTAG, MKBETAG) from common.h to macros.h. -2021-07-22 - xxxxxxxxxx - lavu 57.2.100 - film_grain_params.h +2021-07-22 - e3b5ff17c2e - lavu 57.2.100 - film_grain_params.h Add AV_FILM_GRAIN_PARAMS_H274, AVFilmGrainH274Params -2021-07-19 - xxxxxxxxxx - lavu 57.1.100 - cpu.h +2021-07-19 - c1bf56a526f - lavu 57.1.100 - cpu.h Add av_cpu_force_count() -2021-06-17 - xxxxxxxxxx - lavc 59.2.100 - packet.h +2021-06-17 - aca923b3653 - lavc 59.2.100 - packet.h Add AV_PKT_DATA_DYNAMIC_HDR10_PLUS -2021-06-09 - xxxxxxxxxx - lavf 59.3.100 - avformat.h +2021-06-09 - 2cccab96f6f - lavf 59.3.100 - avformat.h Add pts_wrap_bits to AVStream -2021-xx-xx - xxxxxxxxxx - lavc 59.1.100 - avcodec.h codec.h +2021-06-10 - 7c9763070d9 - lavc 59.1.100 - avcodec.h codec.h Move av_get_profile_name() from avcodec.h to codec.h. -2021-xx-xx - xxxxxxxxxx - lavc 59.1.100 - avcodec.h codec_par.h +2021-06-10 - bb3648e6766 - lavc 59.1.100 - avcodec.h codec_par.h Move av_get_audio_frame_duration2() from avcodec.h to codec_par.h. -2021-xx-xx - xxxxxxxxxx - lavc 59.1.100 - avcodec.h codec_id.h +2021-06-10 - 881db34f6a0 - lavc 59.1.100 - avcodec.h codec_id.h Move av_get_bits_per_sample(), av_get_exact_bits_per_sample(), avcodec_profile_name(), and av_get_pcm_codec() from avcodec.h to codec_id.h. -2021-xx-xx - xxxxxxxxxx - lavc 59.1.100 - avcodec.h defs.h +2021-06-10 - ff0a96046d8 - lavc 59.1.100 - avcodec.h defs.h Add new installed header defs.h. The following definitions are moved into it from avcodec.h: - AVDiscard From f3964a59e1402303ba62f8c72cc78009bfab2300 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 3 Jan 2022 22:08:31 +0100 Subject: [PATCH 671/894] lib*/version.h: Bump Versions before release/5.0 branch Signed-off-by: Michael Niedermayer --- libavcodec/version.h | 4 ++-- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 45c6d13ae7..e2499b505b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 15 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 16 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index 41f568d6b0..56a0fa5c6c 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 1 +#define LIBAVDEVICE_VERSION_MINOR 2 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index a4066fd883..d17abdc5fa 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 21 +#define LIBAVFILTER_VERSION_MINOR 22 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index 79eb22c230..2b51351ccb 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 13 +#define LIBAVFORMAT_VERSION_MINOR 14 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index 3cac09cb96..318045d4c4 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 13 +#define LIBAVUTIL_VERSION_MINOR 14 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index e518ccf810..6dd0b1bcc2 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 0 +#define LIBPOSTPROC_VERSION_MINOR 1 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 5f0d69228c..36220ebe7b 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 0 +#define LIBSWRESAMPLE_VERSION_MINOR 1 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index 8f7b56df9a..e5270811fb 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,8 +27,8 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 1 -#define LIBSWSCALE_VERSION_MICRO 102 +#define LIBSWSCALE_VERSION_MINOR 2 +#define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ From 4be85c9331ca7c3360dffbbd4ce5055e8c478d2e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 3 Jan 2022 22:10:46 +0100 Subject: [PATCH 672/894] lib*/version.h: Bump Versions after release/5.0 branch Signed-off-by: Michael Niedermayer --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index e2499b505b..7a8852bf15 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 16 +#define LIBAVCODEC_VERSION_MINOR 17 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index 56a0fa5c6c..add4d4228a 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 2 +#define LIBAVDEVICE_VERSION_MINOR 3 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index d17abdc5fa..c76f6d22e2 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 22 +#define LIBAVFILTER_VERSION_MINOR 23 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index 2b51351ccb..e8873c8925 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 14 +#define LIBAVFORMAT_VERSION_MINOR 15 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index 318045d4c4..ca5d34d681 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 14 +#define LIBAVUTIL_VERSION_MINOR 15 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index 6dd0b1bcc2..33fd0479b1 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 1 +#define LIBPOSTPROC_VERSION_MINOR 2 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 36220ebe7b..1a786c6a1d 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 1 +#define LIBSWRESAMPLE_VERSION_MINOR 2 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index e5270811fb..aaaf6edc32 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 2 +#define LIBSWSCALE_VERSION_MINOR 3 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From 76e062322c3527b76b9b180ff0caa52b7af4784b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 16:27:28 +0100 Subject: [PATCH 673/894] avformat/movenc: factorize data shifting And move data shift function from movenc to utils. Signed-off-by: Marton Balint --- libavformat/internal.h | 7 ++++++ libavformat/movenc.c | 55 ++--------------------------------------- libavformat/utils.c | 56 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 2ba795d669..63235ce5cf 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -1019,4 +1019,11 @@ void ff_format_set_url(AVFormatContext *s, char *url); void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); +/** + * Make shift_size amount of space at read_start by shifting data in the output + * at read_start until the current IO position. The underlying IO context must + * be seekable. + */ +int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 0f912dd012..40ad4f8642 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -7150,13 +7150,8 @@ static int compute_sidx_size(AVFormatContext *s) static int shift_data(AVFormatContext *s) { - int ret = 0, moov_size; + int moov_size; MOVMuxContext *mov = s->priv_data; - int64_t pos, pos_end; - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; if (mov->flags & FF_MOV_FLAG_FRAGMENT) moov_size = compute_sidx_size(s); @@ -7165,53 +7160,7 @@ static int shift_data(AVFormatContext *s) if (moov_size < 0) return moov_size; - buf = av_malloc(moov_size * 2); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = buf + moov_size; - - /* Shift the data: the AVIO context of the output can only be used for - * writing, so we re-open the same output, but for reading. It also avoids - * a read/seek/write/seek back and forth. */ - avio_flush(s->pb); - ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " - "the second pass (faststart)\n", s->url); - goto end; - } - - /* mark the end of the shift to up to the last data we wrote, and get ready - * for writing */ - pos_end = avio_tell(s->pb); - avio_seek(s->pb, mov->reserved_header_pos + moov_size, SEEK_SET); - - /* start reading at where the new moov will be placed */ - avio_seek(read_pb, mov->reserved_header_pos, SEEK_SET); - pos = avio_tell(read_pb); - -#define READ_BLOCK do { \ - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size); \ - read_buf_id ^= 1; \ -} while (0) - - /* shift data by chunk of at most moov_size */ - READ_BLOCK; - do { - int n; - READ_BLOCK; - n = read_size[read_buf_id]; - if (n <= 0) - break; - avio_write(s->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos < pos_end); - ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; + return ff_format_shift_data(s, mov->reserved_header_pos, moov_size); } static int mov_write_trailer(AVFormatContext *s) diff --git a/libavformat/utils.c b/libavformat/utils.c index 332ba534d2..a78797ef57 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2035,3 +2035,59 @@ const char *av_disposition_to_string(int disposition) return NULL; } + +int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size) +{ + int ret; + int64_t pos, pos_end; + uint8_t *buf, *read_buf[2]; + int read_buf_id = 0; + int read_size[2]; + AVIOContext *read_pb; + + buf = av_malloc_array(shift_size, 2); + if (!buf) + return AVERROR(ENOMEM); + read_buf[0] = buf; + read_buf[1] = buf + shift_size; + + /* Shift the data: the AVIO context of the output can only be used for + * writing, so we re-open the same output, but for reading. It also avoids + * a read/seek/write/seek back and forth. */ + avio_flush(s->pb); + ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url); + goto end; + } + + /* mark the end of the shift to up to the last data we wrote, and get ready + * for writing */ + pos_end = avio_tell(s->pb); + avio_seek(s->pb, read_start + shift_size, SEEK_SET); + + avio_seek(read_pb, read_start, SEEK_SET); + pos = avio_tell(read_pb); + +#define READ_BLOCK do { \ + read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \ + read_buf_id ^= 1; \ +} while (0) + + /* shift data by chunk of at most shift_size */ + READ_BLOCK; + do { + int n; + READ_BLOCK; + n = read_size[read_buf_id]; + if (n <= 0) + break; + avio_write(s->pb, read_buf[read_buf_id], n); + pos += n; + } while (pos < pos_end); + ff_format_io_close(s, &read_pb); + +end: + av_free(buf); + return ret; +} From 10a0a8ca8339589f32e8402f20d054c8bba8c3ff Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 19:00:06 +0100 Subject: [PATCH 674/894] avformat/flvenc: use ff_format_shift_data for data shifting add_keyframe_index seems to generate a corrupted index even before this change. Signed-off-by: Marton Balint --- libavformat/flvenc.c | 59 +++++--------------------------------------- 1 file changed, 6 insertions(+), 53 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 5130d429ad..31d1d93c23 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -576,15 +576,9 @@ static int flv_append_keyframe_info(AVFormatContext *s, FLVContext *flv, double static int shift_data(AVFormatContext *s) { - int ret = 0; - int n = 0; + int ret; int64_t metadata_size = 0; FLVContext *flv = s->priv_data; - int64_t pos, pos_end = avio_tell(s->pb); /* Save the pre-shift size. */ - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */ metadata_size += 2 + 13; /* filepositions String */ @@ -596,58 +590,17 @@ static int shift_data(AVFormatContext *s) if (metadata_size < 0) return metadata_size; - buf = av_malloc_array(metadata_size, 2); - if (!buf) { - return AVERROR(ENOMEM); - } - read_buf[0] = buf; - read_buf[1] = buf + metadata_size; + ret = ff_format_shift_data(s, flv->keyframes_info_offset, metadata_size); + if (ret < 0) + return ret; avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET); avio_wb24(s->pb, flv->metadata_totalsize + metadata_size); - avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET); + avio_seek(s->pb, flv->metadata_totalsize_pos + metadata_size, SEEK_SET); avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size); - /* Shift the data: the AVIO context of the output can only be used for - * writing, so we re-open the same output, but for reading. It also avoids - * a read/seek/write/seek back and forth. */ - avio_flush(s->pb); - ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " - "the second pass (add_keyframe_index)\n", s->url); - goto end; - } - - /* Get ready for writing. */ - avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET); - - /* start reading at where the keyframe index information will be placed */ - avio_seek(read_pb, flv->keyframes_info_offset, SEEK_SET); - pos = avio_tell(read_pb); - -#define READ_BLOCK do { \ - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size); \ - read_buf_id ^= 1; \ -} while (0) - - /* shift data by chunk of at most keyframe *filepositions* and *times* size */ - READ_BLOCK; - do { - READ_BLOCK; - n = read_size[read_buf_id]; - if (n < 0) - break; - avio_write(s->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos <= pos_end); - - ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; + return 0; } static int flv_init(struct AVFormatContext *s) From 26d6c81dc6ed205005dd34f837f52569c1cb3903 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 19:28:50 +0100 Subject: [PATCH 675/894] avformat/segafilmenc: use ff_format_shift_data for shifting Signed-off-by: Marton Balint --- libavformat/segafilmenc.c | 49 ++++----------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index ff8cb66aca..737805faa6 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -170,54 +170,13 @@ static int film_init(AVFormatContext *format_context) static int write_header(AVFormatContext *format_context, uint8_t *header, unsigned header_size) { - int ret = 0; - int64_t pos, pos_end; - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; - - buf = av_malloc(header_size); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = header; - read_size[1] = header_size; - - /* Write the header at the beginning of the file, shifting all content as necessary; - * based on the approach used by MOV faststart. */ - avio_flush(format_context->pb); - ret = format_context->io_open(format_context, &read_pb, format_context->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(format_context, AV_LOG_ERROR, "Unable to re-open %s output file to " - "write the header\n", format_context->url); - av_free(buf); + int ret = ff_format_shift_data(format_context, 0, header_size); + if (ret < 0) return ret; - } - /* Mark the end of the shift to up to the last data we are going to write, - * and get ready for writing */ - pos_end = avio_tell(format_context->pb) + header_size; - pos = avio_seek(format_context->pb, 0, SEEK_SET); + avio_seek(format_context->pb, 0, SEEK_SET); + avio_write(format_context->pb, header, header_size); - /* start reading at where the new header will be placed */ - avio_seek(read_pb, 0, SEEK_SET); - - /* shift data by chunk of at most header_size */ - do { - int n; - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], - header_size); - read_buf_id ^= 1; - n = read_size[read_buf_id]; - if (n <= 0) - break; - avio_write(format_context->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos < pos_end); - ff_format_io_close(format_context, &read_pb); - - av_free(buf); return 0; } From 573b6b8a607398c5f34108efda9c29d41c5727ff Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 19:30:59 +0100 Subject: [PATCH 676/894] avformat/utils: propagate return value of ff_format_io_close in ff_format_shift_data Signed-off-by: Marton Balint --- libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index a78797ef57..23e81bda9d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2085,7 +2085,7 @@ int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size) avio_write(s->pb, read_buf[read_buf_id], n); pos += n; } while (pos < pos_end); - ff_format_io_close(s, &read_pb); + ret = ff_format_io_close(s, &read_pb); end: av_free(buf); From 5c16e463745ece2f18777a5424d7779853d63011 Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:49 +0100 Subject: [PATCH 677/894] avformat/dovi_isom: Implement Dolby Vision configuration parsing/writing Both parse/write implementations are based on mov/movenc. This only adds support for the "Dolby Vision configuration box". Other configuration boxes, such as "Dolby Vision enhancement layer configuration box" are not supported. The new functions will be used to implement parsing/writing the DOVI config for Matroska, as well as to refactor both mov/movenc to use dovi_isom functions. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/dovi_isom.c | 118 ++++++++++++++++++++++++++++++++++++++++ libavformat/dovi_isom.h | 35 ++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 libavformat/dovi_isom.c create mode 100644 libavformat/dovi_isom.h diff --git a/libavformat/dovi_isom.c b/libavformat/dovi_isom.c new file mode 100644 index 0000000000..76681b9451 --- /dev/null +++ b/libavformat/dovi_isom.c @@ -0,0 +1,118 @@ +/* + * DOVI ISO Media common code + * + * Copyright (c) 2020 Vacing Fang + * Copyright (c) 2021 quietvoid + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/dovi_meta.h" + +#include "libavcodec/put_bits.h" + +#include "avformat.h" +#include "dovi_isom.h" + +int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size) +{ + uint32_t buf; + AVDOVIDecoderConfigurationRecord *dovi; + size_t dovi_size; + int ret; + + if (size > (1 << 30) || size < 4) + return AVERROR_INVALIDDATA; + + dovi = av_dovi_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + dovi->dv_version_major = *buf_ptr++; // 8 bits + dovi->dv_version_minor = *buf_ptr++; // 8 bits + + buf = *buf_ptr++ << 8; + buf |= *buf_ptr++; + + dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits + dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits + dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit + dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit + dovi->bl_present_flag = buf & 0x01; // 1 bit + + // Has enough remaining data + if (size >= 5) { + dovi->dv_bl_signal_compatibility_id = ((*buf_ptr++) >> 4) & 0x0f; // 4 bits + } else { + // 0 stands for None + // Dolby Vision V1.2.93 profiles and levels + dovi->dv_bl_signal_compatibility_id = 0; + } + + ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, + (uint8_t *)dovi, dovi_size); + if (ret < 0) { + av_free(dovi); + return ret; + } + + av_log(s, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); + + return 0; +} + +void ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], + AVDOVIDecoderConfigurationRecord *dovi) +{ + PutBitContext pb; + + init_put_bits(&pb, out, ISOM_DVCC_DVVC_SIZE); + + put_bits(&pb, 8, dovi->dv_version_major); + put_bits(&pb, 8, dovi->dv_version_minor); + put_bits(&pb, 7, dovi->dv_profile & 0x7f); + put_bits(&pb, 6, dovi->dv_level & 0x3f); + put_bits(&pb, 1, !!dovi->rpu_present_flag); + put_bits(&pb, 1, !!dovi->el_present_flag); + put_bits(&pb, 1, !!dovi->bl_present_flag); + put_bits(&pb, 4, dovi->dv_bl_signal_compatibility_id & 0x0f); + + put_bits(&pb, 28, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + + flush_put_bits(&pb); + + av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"), + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); +} diff --git a/libavformat/dovi_isom.h b/libavformat/dovi_isom.h new file mode 100644 index 0000000000..1526164319 --- /dev/null +++ b/libavformat/dovi_isom.h @@ -0,0 +1,35 @@ +/* + * DOVI ISO Media common code + * Copyright (c) 2021 quietvoid + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_DOVI_ISOM_H +#define AVFORMAT_DOVI_ISOM_H + +#include "libavutil/dovi_meta.h" + +#include "avformat.h" + +#define ISOM_DVCC_DVVC_SIZE 24 + +int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size); +void ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], + AVDOVIDecoderConfigurationRecord *dovi); + +#endif /* AVFORMAT_DOVI_ISOM_H */ From 05c07943b04de2514343b1de09dc6dca64502643 Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:50 +0100 Subject: [PATCH 678/894] avformat/matroska{dec, enc}: Parse BlockAdditionMapping elements Adds handling of dvcC/dvvC block addition mappings. The parsing creates AVDOVIDecoderConfigurationRecord side data. The configuration block is written when muxing into Matroska, if DOVI side data is present for the track. Most of the Matroska element parsing is based on Plex's FFmpeg source code. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 4 +-- libavformat/matroska.h | 9 ++++++ libavformat/matroskadec.c | 58 +++++++++++++++++++++++++++++++++++++-- libavformat/matroskaenc.c | 37 +++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index e31b248ac0..4464c2b049 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -316,11 +316,11 @@ OBJS-$(CONFIG_M4V_MUXER) += rawenc.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ flac_picture.o isom_tags.o rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ - qtpalette.o replaygain.o + qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ av1.o avc.o hevc.o isom_tags.o \ flacenc_header.o avlanguage.o \ - vorbiscomment.o wv.o + vorbiscomment.o wv.o dovi_isom.o OBJS-$(CONFIG_MCA_DEMUXER) += mca.o OBJS-$(CONFIG_MCC_DEMUXER) += mccdec.o subtitles.o OBJS-$(CONFIG_MD5_MUXER) += hashenc.o diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 2d04a6838b..16491aae22 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -111,6 +111,7 @@ #define MATROSKA_ID_TRACKCONTENTENCODING 0x6240 #define MATROSKA_ID_TRACKTIMECODESCALE 0x23314F #define MATROSKA_ID_TRACKMAXBLKADDID 0x55EE +#define MATROSKA_ID_TRACKBLKADDMAPPING 0x41E4 /* IDs in the trackvideo master */ #define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3 @@ -189,6 +190,12 @@ #define MATROSKA_ID_ENCODINGSIGKEYID 0x47E4 #define MATROSKA_ID_ENCODINGSIGNATURE 0x47E3 +/* IDs in the block addition mapping master */ +#define MATROSKA_ID_BLKADDIDVALUE 0x41F0 +#define MATROSKA_ID_BLKADDIDNAME 0x41A4 +#define MATROSKA_ID_BLKADDIDTYPE 0x41E7 +#define MATROSKA_ID_BLKADDIDEXTRADATA 0x41ED + /* ID in the cues master */ #define MATROSKA_ID_POINTENTRY 0xBB @@ -385,4 +392,6 @@ extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_P int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); +#define DVCC_DVVC_BLOCK_TYPE_NAME "Dolby Vision configuration" + #endif /* AVFORMAT_MATROSKA_H */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a4bbbe954e..6ce553205d 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -53,6 +53,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "internal.h" #include "isom.h" #include "matroska.h" @@ -239,6 +240,13 @@ typedef struct MatroskaTrackOperation { EbmlList combine_planes; } MatroskaTrackOperation; +typedef struct MatroskaBlockAdditionMapping { + uint64_t value; + char *name; + uint64_t type; + EbmlBin extradata; +} MatroskaBlockAdditionMapping; + typedef struct MatroskaTrack { uint64_t num; uint64_t uid; @@ -269,6 +277,7 @@ typedef struct MatroskaTrack { int ms_compat; int needs_decoding; uint64_t max_block_additional_id; + EbmlList block_addition_mappings; uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -419,8 +428,8 @@ typedef struct MatroskaDemuxContext { // incomplete type (6.7.2 in C90, 6.9.2 in C99). // Removing the sizes breaks MSVC. static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], - matroska_track[32], matroska_track_encoding[6], matroska_track_encodings[2], - matroska_track_combine_planes[2], matroska_track_operation[2], matroska_tracks[2], + matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], + matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; @@ -570,6 +579,14 @@ static EbmlSyntax matroska_track_operation[] = { CHILD_OF(matroska_track) }; +static EbmlSyntax matroska_block_addition_mapping[] = { + { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, value) }, + { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, + { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type) }, + { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, + CHILD_OF(matroska_track) +}; + static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, @@ -593,6 +610,7 @@ static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, 0, { .n = matroska_track_encodings } }, { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, max_block_additional_id), { .u = 0 } }, + { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, 0, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll), { .u = 0 } }, { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, @@ -2311,6 +2329,38 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, return 0; } +static int mkv_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const MatroskaTrack *track, + EbmlBin *bin) +{ + return ff_isom_parse_dvcc_dvvc(s, st, bin->data, bin->size); +} + +static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, const MatroskaTrack *track) +{ + const EbmlList *mappings_list = &track->block_addition_mappings; + MatroskaBlockAdditionMapping *mappings = mappings_list->elem; + int ret; + + for (int i = 0; i < mappings_list->nb_elem; i++) { + MatroskaBlockAdditionMapping *mapping = &mappings[i]; + + switch (mapping->type) { + case MKBETAG('d','v','c','C'): + case MKBETAG('d','v','v','C'): + if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) + return ret; + + break; + default: + av_log(s, AV_LOG_DEBUG, + "Unknown block additional mapping type 0x%"PRIx64", value %"PRIu64", name \"%s\"\n", + mapping->type, mapping->value, mapping->name ? mapping->name : ""); + } + } + + return 0; +} + static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id) { const AVCodecTag *codec_tags; @@ -2898,6 +2948,10 @@ static int matroska_parse_tracks(AVFormatContext *s) if (track->flag_textdescriptions) st->disposition |= AV_DISPOSITION_DESCRIPTIONS; } + + ret = mkv_parse_block_addition_mappings(s, st, track); + if (ret < 0) + return ret; } return 0; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 8c4cf4024a..5cc59dc9f8 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "avio_internal.h" #include "avlanguage.h" +#include "dovi_isom.h" #include "flacenc.h" #include "internal.h" #include "isom.h" @@ -1120,6 +1121,37 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; } +static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) +{ + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) + av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); + + if (dovi && dovi->dv_profile <= 10) { + ebml_master mapping; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + uint32_t type; + + uint64_t expected_size = (2 + 1 + (sizeof(DVCC_DVVC_BLOCK_TYPE_NAME) - 1)) + + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE); + + if (dovi->dv_profile > 7) { + type = MKBETAG('d', 'v', 'v', 'C'); + } else { + type = MKBETAG('d', 'v', 'c', 'C'); + } + + ff_isom_put_dvcc_dvvc(s, buf, dovi); + + mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, expected_size); + + put_ebml_string(pb, MATROSKA_ID_BLKADDIDNAME, DVCC_DVVC_BLOCK_TYPE_NAME); + put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type); + put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, sizeof(buf)); + + end_ebml_master(pb, mapping); + } +} + static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, AVStream *st, mkv_track *track, AVIOContext *pb, int is_default) @@ -1319,6 +1351,11 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, mkv_write_video_projection(s, pb, st); end_ebml_master(pb, subinfo); + + if (mkv->mode != MODE_WEBM) { + mkv_write_dovi(s, pb, st); + } + break; case AVMEDIA_TYPE_AUDIO: From 9906f9ae3b678d95b413dd4320e334ea3e2cf70a Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:51 +0100 Subject: [PATCH 679/894] avformat/mov: Refactor mov_read_dvcc_dvvc to use ff_isom_parse_dvcc_dvvc To avoid duplicating code. The implementation in dovi_isom is identical. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 2 +- libavformat/mov.c | 50 +++++++------------------------------------- 2 files changed, 8 insertions(+), 44 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 4464c2b049..cd9810ba01 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -339,7 +339,7 @@ OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o OBJS-$(CONFIG_MODS_DEMUXER) += mods.o OBJS-$(CONFIG_MOFLEX_DEMUXER) += moflex.o OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \ - qtpalette.o replaygain.o + qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ movenccenc.o movenc_ttml.o rawutils.o diff --git a/libavformat/mov.c b/libavformat/mov.c index 351ecde770..ad5ab6b491 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -55,6 +55,7 @@ #include "avformat.h" #include "internal.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "riff.h" #include "isom.h" #include "libavcodec/get_bits.h" @@ -7062,58 +7063,21 @@ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; - uint32_t buf; - AVDOVIDecoderConfigurationRecord *dovi; - size_t dovi_size; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; int ret; + int64_t read_size = atom.size; if (c->fc->nb_streams < 1) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - if ((uint64_t)atom.size > (1<<30) || atom.size < 4) - return AVERROR_INVALIDDATA; + // At most 24 bytes + read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE); - dovi = av_dovi_alloc(&dovi_size); - if (!dovi) - return AVERROR(ENOMEM); - - dovi->dv_version_major = avio_r8(pb); - dovi->dv_version_minor = avio_r8(pb); - - buf = avio_rb16(pb); - dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits - dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits - dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit - dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit - dovi->bl_present_flag = buf & 0x01; // 1 bit - if (atom.size >= 24) { // 4 + 4 + 4 * 4 - buf = avio_r8(pb); - dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits - } else { - // 0 stands for None - // Dolby Vision V1.2.93 profiles and levels - dovi->dv_bl_signal_compatibility_id = 0; - } - - ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, - (uint8_t *)dovi, dovi_size); - if (ret < 0) { - av_free(dovi); + if ((ret = ffio_read_size(pb, buf, read_size)) < 0) return ret; - } - av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_version_major, dovi->dv_version_minor, - dovi->dv_profile, dovi->dv_level, - dovi->rpu_present_flag, - dovi->el_present_flag, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id - ); - - return 0; + return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size); } static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom) From f0fb005f59f6febcf2ffc8140bdb7f136ac56add Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:52 +0100 Subject: [PATCH 680/894] avformat/movenc: Refactor mov_write_dvcc_dvvc_tag to use ff_isom_put_dvcc_dvvc Improves code legibility by not using bit shifts. Also avoids duplicating the dvcC/dvvC ISOM box writing code. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 3 ++- libavformat/movenc.c | 22 ++++++---------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index cd9810ba01..a9afb9c042 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -342,7 +342,8 @@ OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \ qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ - movenccenc.o movenc_ttml.o rawutils.o + movenccenc.o movenc_ttml.o rawutils.o \ + dovi_isom.o OBJS-$(CONFIG_MP2_MUXER) += rawenc.o OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 40ad4f8642..04cf2f777d 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -27,6 +27,7 @@ #include "movenc.h" #include "avformat.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "riff.h" #include "avio.h" #include "isom.h" @@ -1911,6 +1912,8 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi) { + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + avio_wb32(pb, 32); /* size = 8 + 24 */ if (dovi->dv_profile > 10) ffio_wfourcc(pb, "dvwC"); @@ -1918,23 +1921,10 @@ static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDe ffio_wfourcc(pb, "dvvC"); else ffio_wfourcc(pb, "dvcC"); - avio_w8(pb, dovi->dv_version_major); - avio_w8(pb, dovi->dv_version_minor); - avio_wb16(pb, (dovi->dv_profile << 9) | (dovi->dv_level << 3) | - (dovi->rpu_present_flag << 2) | (dovi->el_present_flag << 1) | - dovi->bl_present_flag); - avio_wb32(pb, (dovi->dv_bl_signal_compatibility_id << 28) | 0); - ffio_fill(pb, 0, 4 * 4); /* reserved */ - av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"), - dovi->dv_version_major, dovi->dv_version_minor, - dovi->dv_profile, dovi->dv_level, - dovi->rpu_present_flag, - dovi->el_present_flag, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id); + ff_isom_put_dvcc_dvvc(s, buf, dovi); + avio_write(pb, buf, sizeof(buf)); + return 32; /* 8 + 24 */ } From 3485e79f07d74e47ff00b60a68d609d37d0129ba Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 15 Dec 2021 23:21:25 +0100 Subject: [PATCH 681/894] avformat/(aiff|flac|mov|mp3|tta)enc: Don't create unnecessary references The packet given to muxers is not used afterwards; it is always unreferenced by libavformat. Ergo muxers are allowed to keep the references in the packets and e.g. move the ownership to a packet list. This is what this commit does. Signed-off-by: Andreas Rheinhardt --- libavformat/aiffenc.c | 2 +- libavformat/flacenc.c | 2 +- libavformat/movenc.c | 4 +++- libavformat/mp3enc.c | 3 ++- libavformat/ttaenc.c | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 24bc17400e..7bb0978a53 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -219,7 +219,7 @@ static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; return avpriv_packet_list_put(&aiff->pict_list, &aiff->pict_list_end, - pkt, av_packet_ref, 0); + pkt, NULL, 0); } return 0; diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index f884e5d2c8..e8f043729e 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -360,7 +360,7 @@ static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == c->audio_stream_idx) { if (c->waiting_pics) { /* buffer audio packets until we get all the pictures */ - ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, av_packet_ref, 0); + ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); c->waiting_pics = 0; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 04cf2f777d..e5391bb80f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6187,9 +6187,11 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } + /* The following will reset pkt and is only allowed to be used + * because we return immediately. afterwards. */ if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue, &trk->squashed_packet_queue_end, - pkt, av_packet_ref, 0)) < 0) { + pkt, NULL, 0)) < 0) { return ret; } diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index e4b2a65b07..5728ef30be 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -524,7 +524,8 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, pkt, av_packet_ref, 0); + int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, + pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 11855c32d9..5f21fdc144 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -95,10 +95,11 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) int ret; ret = avpriv_packet_list_put(&tta->queue, &tta->queue_end, pkt, - av_packet_ref, 0); + NULL, 0); if (ret < 0) { return ret; } + pkt = &tta->queue_end->pkt; avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; From 20b0d24c2f7ae86cebeb17399a2fea3a7e3d0f69 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Feb 2021 12:40:04 +0100 Subject: [PATCH 682/894] Makefile: Redo duplicating object files in shared builds In case of shared builds, some object files containing tables are currently duplicated into other libraries: log2_tab.c, golomb.c, reverse.c. The check for whether this is duplicated is simply whether CONFIG_SHARED is true. Yet this is crude: E.g. libavdevice includes reverse.c for shared builds, but only needs it for the decklink input device, which given that decklink is not enabled by default will be unused in most libavdevice.so. This commit changes this by making it more explicit about what to duplicate from other libraries. To do this, two new Makefile variables were added: SHLIBOBJS and STLIBOBJS. SHLIBOBJS contains the objects that are duplicated from other libraries in case of shared builds; STLIBOBJS contains stuff that a library has to provide for other libraries in case of static builds. These new variables provide a way to enable/disable with a finer granularity than just whether shared builds are enabled or not. E.g. lavd's Makefile now contains: SHLIBOBJS-$(CONFIG_DECKLINK_INDEV) += reverse.o Another example is provided by the golomb tables. These are provided by lavc for static builds, even if one uses a build configuration that makes only lavf use them. Therefore lavc's Makefile contains STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o, whereas lavf's Makefile has a corresponding SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o. E.g. in case the MXF muxer is the only component needing these tables only libavformat.so will contain them for shared builds; currently libavcodec.so does so, too. (There is currently a CONFIG_EXTRA group for golomb. But actually one would need two groups (golomb_avcodec and golomb_avformat) in order to know when and where to include these tables. Therefore this commit uses a Makefile-based approach for this and stops using these groups for the users in libavformat.) Signed-off-by: Andreas Rheinhardt --- Makefile | 3 ++- configure | 4 ++-- ffbuild/common.mak | 10 ++++++++-- ffbuild/library.mak | 22 +++++++++++++++++++--- libavcodec/Makefile | 10 ++++++++-- libavdevice/Makefile | 4 +++- libavfilter/Makefile | 5 +++-- libavformat/Makefile | 6 +++++- libswresample/Makefile | 4 +++- libswscale/Makefile | 3 ++- 10 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 5479554683..2d622ecd9c 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,8 @@ SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \ ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \ ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \ MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \ - MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS HOSTOBJS TESTOBJS + MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS SHLIBOBJS \ + STLIBOBJS HOSTOBJS TESTOBJS define RESET $(1) := diff --git a/configure b/configure index e2ea473565..e16a5f34f6 100755 --- a/configure +++ b/configure @@ -3436,7 +3436,7 @@ mp4_muxer_select="mov_muxer" mpegts_demuxer_select="iso_media" mpegts_muxer_select="ac3_parser adts_muxer latm_muxer h264_mp4toannexb_bsf hevc_mp4toannexb_bsf" mpegtsraw_demuxer_select="mpegts_demuxer" -mxf_muxer_select="golomb pcm_rechunk_bsf" +mxf_muxer_select="pcm_rechunk_bsf" mxf_d10_muxer_select="mxf_muxer" mxf_opatom_muxer_select="mxf_muxer" nut_muxer_select="riffenc" @@ -3449,7 +3449,7 @@ ogv_muxer_select="ogg_muxer" opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtp_muxer_select="golomb jpegtables" +rtp_muxer_select="jpegtables" rtp_mpegts_muxer_select="mpegts_muxer rtp_muxer" rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" rtsp_demuxer_select="http_protocol rtpdec" diff --git a/ffbuild/common.mak b/ffbuild/common.mak index c13148f476..42f7b23641 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -157,6 +157,8 @@ include $(SRC_PATH)/ffbuild/arch.mak OBJS += $(OBJS-yes) SLIBOBJS += $(SLIBOBJS-yes) +SHLIBOBJS += $(SHLIBOBJS-yes) +STLIBOBJS += $(STLIBOBJS-yes) FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS) TESTPROGS += $(TESTPROGS-yes) @@ -165,6 +167,8 @@ FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%= OBJS := $(sort $(OBJS:%=$(SUBDIR)%)) SLIBOBJS := $(sort $(SLIBOBJS:%=$(SUBDIR)%)) +SHLIBOBJS := $(sort $(SHLIBOBJS:%=$(SUBDIR)%)) +STLIBOBJS := $(sort $(STLIBOBJS:%=$(SUBDIR)%)) TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o) TESTPROGS := $(TESTPROGS:%=$(SUBDIR)tests/%$(EXESUF)) HOSTOBJS := $(HOSTPROGS:%=$(SUBDIR)%.o) @@ -200,10 +204,12 @@ $(OBJS): | $(sort $(dir $(OBJS))) $(HOBJS): | $(sort $(dir $(HOBJS))) $(HOSTOBJS): | $(sort $(dir $(HOSTOBJS))) $(SLIBOBJS): | $(sort $(dir $(SLIBOBJS))) +$(SHLIBOBJS): | $(sort $(dir $(SHLIBOBJS))) +$(STLIBOBJS): | $(sort $(dir $(STLIBOBJS))) $(TESTOBJS): | $(sort $(dir $(TESTOBJS))) $(TOOLOBJS): | tools -OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(TESTOBJS)) +OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(SHLIBOBJS) $(STLIBOBJS) $(TESTOBJS)) CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.pc *.ptx *.ptx.gz *.ptx.c *.ver *.version *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a @@ -215,4 +221,4 @@ endef $(eval $(RULES)) --include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d) +-include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SHLIBOBJS:.o=.d) $(STLIBOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d) diff --git a/ffbuild/library.mak b/ffbuild/library.mak index 612bacb980..ad09f20da9 100644 --- a/ffbuild/library.mak +++ b/ffbuild/library.mak @@ -14,10 +14,26 @@ INSTHEADERS := $(INSTHEADERS) $(HEADERS:%=$(SUBDIR)%) all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME) $(SUBDIR)lib$(FULLNAME).pc all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) $(SUBDIR)lib$(FULLNAME).pc -LIBOBJS := $(OBJS) $(SUBDIR)%.h.o $(TESTOBJS) +LIBOBJS := $(OBJS) $(SHLIBOBJS) $(STLIBOBJS) $(SUBDIR)%.h.o $(TESTOBJS) $(LIBOBJS) $(LIBOBJS:.o=.s) $(LIBOBJS:.o=.i): CPPFLAGS += -DHAVE_AV_CONFIG_H -$(SUBDIR)$(LIBNAME): $(OBJS) +ifdef CONFIG_SHARED +# In case both shared libs and static libs are enabled, it can happen +# that a user might want to link e.g. libavformat statically, but +# libavcodec and the other libs dynamically. In this case +# libavformat won't be able to access libavcodec's internal symbols, +# so that they have to be duplicated into the archive just like +# for purely shared builds. +# Test programs are always statically linked against their library +# to be able to access their library's internals, even with shared builds. +# Yet linking against dependend libraries still uses dynamic linking. +# This means that we are in the scenario described above. +# In case only static libs are used, the linker will only use +# one of these copies; this depends on the duplicated object files +# containing exactly the same symbols. +OBJS += $(SHLIBOBJS) +endif +$(SUBDIR)$(LIBNAME): $(OBJS) $(STLIBOBJS) $(RM) $@ $(AR) $(ARFLAGS) $(AR_O) $^ $(RANLIB) $@ @@ -48,7 +64,7 @@ $(SUBDIR)lib$(NAME).ver: $(SUBDIR)lib$(NAME).v $(OBJS) $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR) $(Q)cd ./$(SUBDIR) && $(LN_S) $(SLIBNAME_WITH_MAJOR) $(SLIBNAME) -$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver +$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SHLIBOBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver $(SLIB_CREATE_DEF_CMD) $$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS) $(SLIB_EXTRA_CMD) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9577062eec..79c4275133 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -139,7 +139,6 @@ OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o OBJS-$(CONFIG_RDFT) += rdft.o OBJS-$(CONFIG_RV34DSP) += rv34dsp.o -OBJS-$(CONFIG_SHARED) += log2_tab.o reverse.o OBJS-$(CONFIG_SINEWIN) += sinewin.o OBJS-$(CONFIG_SNAPPY) += snappy.o OBJS-$(CONFIG_STARTCODE) += startcode.o @@ -981,7 +980,10 @@ OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o -# libavformat dependencies +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o reverse.o + +# General libavformat dependencies OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o @@ -997,6 +999,10 @@ OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o +# libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o + # libavfilter dependencies OBJS-$(CONFIG_ELBG_FILTER) += elbg.o diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 0dfe47a1f4..53efda0514 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -9,7 +9,6 @@ OBJS = alldevices.o \ utils.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o -OBJS-$(CONFIG_SHARED) += reverse.o # input/output devices OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o timefilter.o @@ -54,6 +53,9 @@ OBJS-$(CONFIG_XV_OUTDEV) += xv.o OBJS-$(CONFIG_LIBCDIO_INDEV) += libcdio.o OBJS-$(CONFIG_LIBDC1394_INDEV) += libdc1394.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS-$(CONFIG_DECKLINK_INDEV) += reverse.o + # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avdeviceres.o diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 090944a99c..01c0338bbb 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -577,13 +577,14 @@ OBJS-$(CONFIG_SPECTRUMSYNTH_FILTER) += vaf_spectrumsynth.o OBJS-$(CONFIG_AMOVIE_FILTER) += src_movie.o OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o + # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avfilterres.o SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h -OBJS-$(CONFIG_SHARED) += log2_tab.o - SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h diff --git a/libavformat/Makefile b/libavformat/Makefile index a9afb9c042..37281d5ca8 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -61,7 +61,6 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \ rtpdec_vp9.o \ rtpdec_xiph.o OBJS-$(CONFIG_RTPENC_CHAIN) += rtpenc_chain.o rtp.o -OBJS-$(CONFIG_SHARED) += log2_tab.o golomb_tab.o OBJS-$(CONFIG_SRTP) += srtp.o # muxers/demuxers @@ -680,6 +679,11 @@ OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o + # libavdevice dependencies OBJS-$(CONFIG_IEC61883_INDEV) += dv.o diff --git a/libswresample/Makefile b/libswresample/Makefile index 42666e4dd2..f528427f55 100644 --- a/libswresample/Makefile +++ b/libswresample/Makefile @@ -15,7 +15,9 @@ OBJS = audioconvert.o \ swresample_frame.o \ OBJS-$(CONFIG_LIBSOXR) += soxr_resample.o -OBJS-$(CONFIG_SHARED) += log2_tab.o + +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += swresampleres.o diff --git a/libswscale/Makefile b/libswscale/Makefile index 4b8f9de425..a0ec71e06f 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -19,7 +19,8 @@ OBJS = alphablend.o \ yuv2rgb.o \ vscale.o \ -OBJS-$(CONFIG_SHARED) += log2_tab.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += swscaleres.o From 41457e536c059d265844b1a66c906a9a842f73ab Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 16 Dec 2021 00:23:48 +0100 Subject: [PATCH 683/894] avformat/mux, mxfenc: Don't use sizeof(AVPacket) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes one of the last usages of sizeof(AVPacket) in the generic muxing code. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mux.c | 8 +------- libavformat/mxfenc.c | 8 ++------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index d93dc73f8e..3ba95d28c6 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -1014,15 +1014,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, AVStream *const st = s->streams[pktl->pkt.stream_index]; FFStream *const sti = ffstream(st); - *pkt = pktl->pkt; - - si->packet_buffer = pktl->next; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; - if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; - av_freep(&pktl); + avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, pkt); return 1; } else { diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 873d64a5fd..4c02e3e264 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -3128,14 +3128,10 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus pktl = si->packet_buffer; } - *out = pktl->pkt; - av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts); - si->packet_buffer = pktl->next; if (ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer == pktl) ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer = NULL; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; - av_freep(&pktl); + avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, out); + av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", out->stream_index, out->dts); return 1; } else { out: From 029598bd4aa696253370c4429abe3c2c95f2e788 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 16 Dec 2021 02:16:29 +0100 Subject: [PATCH 684/894] avformat/movenc: Use dedicated pointer for access to MOVTrack Improves readability and slightly decreases codesize. While just at it, also remove a check whether the packet list is nonempty before freeing it, as freeing an empty list is fine and basically a no-op. Signed-off-by: Andreas Rheinhardt --- libavformat/movenc.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index e5391bb80f..24965c89c2 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6457,29 +6457,29 @@ static void mov_free(AVFormatContext *s) } for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) - ff_mov_close_hinting(&mov->tracks[i]); - else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) - av_freep(&mov->tracks[i].par); - av_freep(&mov->tracks[i].cluster); - av_freep(&mov->tracks[i].frag_info); - av_packet_free(&mov->tracks[i].cover_image); + MOVTrack *const track = &mov->tracks[i]; - if (mov->tracks[i].eac3_priv) { - struct eac3_info *info = mov->tracks[i].eac3_priv; + if (track->tag == MKTAG('r','t','p',' ')) + ff_mov_close_hinting(track); + else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) + av_freep(&track->par); + av_freep(&track->cluster); + av_freep(&track->frag_info); + av_packet_free(&track->cover_image); + + if (track->eac3_priv) { + struct eac3_info *info = track->eac3_priv; av_packet_free(&info->pkt); - av_freep(&mov->tracks[i].eac3_priv); + av_freep(&track->eac3_priv); } - if (mov->tracks[i].vos_len) - av_freep(&mov->tracks[i].vos_data); + if (track->vos_len) + av_freep(&track->vos_data); - ff_mov_cenc_free(&mov->tracks[i].cenc); - ffio_free_dyn_buf(&mov->tracks[i].mdat_buf); + ff_mov_cenc_free(&track->cenc); + ffio_free_dyn_buf(&track->mdat_buf); - if (mov->tracks[i].squashed_packet_queue) { - avpriv_packet_list_free(&(mov->tracks[i].squashed_packet_queue), - &(mov->tracks[i].squashed_packet_queue_end)); - } + avpriv_packet_list_free(&track->squashed_packet_queue, + &track->squashed_packet_queue_end); } av_freep(&mov->tracks); From 4c03928f4db4dab5ebed91c281e67f678cd3349d Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Sun, 2 Jan 2022 09:22:26 -0800 Subject: [PATCH 685/894] avformat/imf: Fix error handling in set_context_streams_from_tracks() Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/imfdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index 228ba494ae..503c8a2659 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -564,9 +564,8 @@ static int set_context_streams_from_tracks(AVFormatContext *s) /* Copy stream information */ asset_stream = avformat_new_stream(s, NULL); if (!asset_stream) { - ret = AVERROR(ENOMEM); av_log(s, AV_LOG_ERROR, "Could not create stream\n"); - break; + return AVERROR(ENOMEM); } asset_stream->id = i; ret = avcodec_parameters_copy(asset_stream->codecpar, first_resource_stream->codecpar); From 20b0b2be6c6f7c2c3949e4e004fad78748e76b9b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 10:25:08 +0100 Subject: [PATCH 686/894] avformat/tests/imf: Don't use uninitialized value Reviewed-by: Zane van Iperen Signed-off-by: Andreas Rheinhardt --- libavformat/tests/imf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index 68e4c8b6af..142aa04261 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -347,7 +347,7 @@ static int test_bad_cpl_parsing(void) doc = xmlReadMemory(cpl_bad_doc, strlen(cpl_bad_doc), NULL, NULL, 0); if (doc == NULL) { printf("XML parsing failed.\n"); - return ret; + return 1; } ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); From 78dc21b123e71ef49f45390d826a1c25e3805ec7 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 09:55:11 +0100 Subject: [PATCH 687/894] lavu/frame: Add Dolby Vision metadata side data type In order to be able to extend this struct later (as the Dolby Vision RPU evolves), all of the 'container' structs are considered extensible, and the individual constituent fields must instead be accessed via offsets. The precedent for this style of access is set in Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- doc/APIchanges | 3 + libavutil/dovi_meta.c | 25 +++++++ libavutil/dovi_meta.h | 166 ++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.c | 1 + libavutil/frame.h | 9 ++- libavutil/version.h | 2 +- 6 files changed, 204 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 50b5f0bb53..0fb3f1e3d7 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2022-01-04 - xxxxxxxxxx - lavu 57.16.100 - frame.h + Add AV_FRAME_DATA_DOVI_METADATA. + 2022-01-03 - 70f318e6b6c - lavf 59.13.100 - avformat.h Add AVFMT_EXPERIMENTAL flag. diff --git a/libavutil/dovi_meta.c b/libavutil/dovi_meta.c index 7bd08f6c54..9c50da561e 100644 --- a/libavutil/dovi_meta.c +++ b/libavutil/dovi_meta.c @@ -33,3 +33,28 @@ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size) return dovi; } + +typedef struct AVDOVIMetadataInternal { + AVDOVIMetadata metadata; + AVDOVIRpuDataHeader header; + AVDOVIDataMapping mapping; + AVDOVIColorMetadata color; +} AVDOVIMetadataInternal; + +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size) +{ + AVDOVIMetadataInternal *dovi = av_mallocz(sizeof(AVDOVIMetadataInternal)); + if (!dovi) + return NULL; + + if (size) + *size = sizeof(*dovi); + + dovi->metadata = (struct AVDOVIMetadata) { + .header_offset = offsetof(AVDOVIMetadataInternal, header), + .mapping_offset = offsetof(AVDOVIMetadataInternal, mapping), + .color_offset = offsetof(AVDOVIMetadataInternal, color), + }; + + return &dovi->metadata; +} diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h index 299911d434..3d11e02bff 100644 --- a/libavutil/dovi_meta.h +++ b/libavutil/dovi_meta.h @@ -29,6 +29,7 @@ #include #include +#include "rational.h" /* * DOVI configuration @@ -67,4 +68,169 @@ typedef struct AVDOVIDecoderConfigurationRecord { */ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size); +/** + * Dolby Vision RPU data header. + * + * @note sizeof(AVDOVIRpuDataHeader) is not part of the public ABI. + */ +typedef struct AVDOVIRpuDataHeader { + uint8_t rpu_type; + uint16_t rpu_format; + uint8_t vdr_rpu_profile; + uint8_t vdr_rpu_level; + uint8_t chroma_resampling_explicit_filter_flag; + uint8_t coef_data_type; /* informative, lavc always converts to fixed */ + uint8_t coef_log2_denom; + uint8_t vdr_rpu_normalized_idc; + uint8_t bl_video_full_range_flag; + uint8_t bl_bit_depth; /* [8, 16] */ + uint8_t el_bit_depth; /* [8, 16] */ + uint8_t vdr_bit_depth; /* [8, 16] */ + uint8_t spatial_resampling_filter_flag; + uint8_t el_spatial_resampling_filter_flag; + uint8_t disable_residual_flag; +} AVDOVIRpuDataHeader; + +enum AVDOVIMappingMethod { + AV_DOVI_MAPPING_POLYNOMIAL = 0, + AV_DOVI_MAPPING_MMR = 1, +}; + +/** + * Coefficients of a piece-wise function. The pieces of the function span the + * value ranges between two adjacent pivot values. + */ +#define AV_DOVI_MAX_PIECES 8 +typedef struct AVDOVIReshapingCurve { + uint8_t num_pivots; /* [2, 9] */ + uint16_t pivots[AV_DOVI_MAX_PIECES + 1]; /* sorted ascending */ + enum AVDOVIMappingMethod mapping_idc[AV_DOVI_MAX_PIECES]; + /* AV_DOVI_MAPPING_POLYNOMIAL */ + uint8_t poly_order[AV_DOVI_MAX_PIECES]; /* [1, 2] */ + int64_t poly_coef[AV_DOVI_MAX_PIECES][3]; /* x^0, x^1, x^2 */ + /* AV_DOVI_MAPPING_MMR */ + uint8_t mmr_order[AV_DOVI_MAX_PIECES]; /* [1, 3] */ + int64_t mmr_constant[AV_DOVI_MAX_PIECES]; + int64_t mmr_coef[AV_DOVI_MAX_PIECES][3/* order - 1 */][7]; +} AVDOVIReshapingCurve; + +enum AVDOVINLQMethod { + AV_DOVI_NLQ_NONE = -1, + AV_DOVI_NLQ_LINEAR_DZ = 0, +}; + +/** + * Coefficients of the non-linear inverse quantization. For the interpretation + * of these, see ETSI GS CCM 001. + */ +typedef struct AVDOVINLQParams { + uint16_t nlq_offset; + uint64_t vdr_in_max; + /* AV_DOVI_NLQ_LINEAR_DZ */ + uint64_t linear_deadzone_slope; + uint64_t linear_deadzone_threshold; +} AVDOVINLQParams; + +/** + * Dolby Vision RPU data mapping parameters. + * + * @note sizeof(AVDOVIDataMapping) is not part of the public ABI. + */ +typedef struct AVDOVIDataMapping { + uint8_t vdr_rpu_id; + uint8_t mapping_color_space; + uint8_t mapping_chroma_format_idc; + AVDOVIReshapingCurve curves[3]; /* per component */ + + /* Non-linear inverse quantization */ + enum AVDOVINLQMethod nlq_method_idc; + uint32_t num_x_partitions; + uint32_t num_y_partitions; + AVDOVINLQParams nlq[3]; /* per component */ +} AVDOVIDataMapping; + +/** + * Dolby Vision RPU colorspace metadata parameters. + * + * @note sizeof(AVDOVIColorMetadata) is not part of the public ABI. + */ +typedef struct AVDOVIColorMetadata { + uint8_t dm_metadata_id; + uint8_t scene_refresh_flag; + + /** + * Coefficients of the custom Dolby Vision IPT-PQ matrices. These are to be + * used instead of the matrices indicated by the frame's colorspace tags. + * The output of rgb_to_lms_matrix is to be fed into a BT.2020 LMS->RGB + * matrix based on a Hunt-Pointer-Estevez transform, but without any + * crosstalk. (See the definition of the ICtCp colorspace for more + * information.) + */ + AVRational ycc_to_rgb_matrix[9]; /* before PQ linearization */ + AVRational ycc_to_rgb_offset[3]; /* input offset of neutral value */ + AVRational rgb_to_lms_matrix[9]; /* after PQ linearization */ + + /** + * Extra signal metadata (see Dolby patents for more info). + */ + uint16_t signal_eotf; + uint16_t signal_eotf_param0; + uint16_t signal_eotf_param1; + uint32_t signal_eotf_param2; + uint8_t signal_bit_depth; + uint8_t signal_color_space; + uint8_t signal_chroma_format; + uint8_t signal_full_range_flag; /* [0, 3] */ + uint16_t source_min_pq; + uint16_t source_max_pq; + uint16_t source_diagonal; +} AVDOVIColorMetadata; + +/** + * Combined struct representing a combination of header, mapping and color + * metadata, for attaching to frames as side data. + * + * @note The struct must be allocated with av_dovi_metadata_alloc() and + * its size is not a part of the public ABI. + */ + +typedef struct AVDOVIMetadata { + /** + * Offset in bytes from the beginning of this structure at which the + * respective structs start. + */ + size_t header_offset; /* AVDOVIRpuDataHeader */ + size_t mapping_offset; /* AVDOVIDataMapping */ + size_t color_offset; /* AVDOVIColorMetadata */ +} AVDOVIMetadata; + +static av_always_inline AVDOVIRpuDataHeader * +av_dovi_get_header(const AVDOVIMetadata *data) +{ + return (AVDOVIRpuDataHeader *)((uint8_t *) data + data->header_offset); +} + +static av_always_inline AVDOVIDataMapping * +av_dovi_get_mapping(const AVDOVIMetadata *data) +{ + return (AVDOVIDataMapping *)((uint8_t *) data + data->mapping_offset); +} + +static av_always_inline AVDOVIColorMetadata * +av_dovi_get_color(const AVDOVIMetadata *data) +{ + return (AVDOVIColorMetadata *)((uint8_t *) data + data->color_offset); +} + +/** + * Allocate an AVDOVIMetadata structure and initialize its + * fields to default values. + * + * @param size If this parameter is non-NULL, the size in bytes of the + * allocated struct will be written here on success + * + * @return the newly allocated struct or NULL on failure + */ +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size); + #endif /* AVUTIL_DOVI_META_H */ diff --git a/libavutil/frame.c b/libavutil/frame.c index 0912ad9131..8997c85e35 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -729,6 +729,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters"; case AV_FRAME_DATA_DETECTION_BBOXES: return "Bounding boxes for object detection and classification"; case AV_FRAME_DATA_DOVI_RPU_BUFFER: return "Dolby Vision RPU Data"; + case AV_FRAME_DATA_DOVI_METADATA: return "Dolby Vision Metadata"; } return NULL; } diff --git a/libavutil/frame.h b/libavutil/frame.h index 3f295f6b9e..18e239f870 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -189,11 +189,18 @@ enum AVFrameSideDataType { AV_FRAME_DATA_DETECTION_BBOXES, /** - * Dolby Vision RPU data, suitable for passing to x265 + * Dolby Vision RPU raw data, suitable for passing to x265 * or other libraries. Array of uint8_t, with NAL emulation * bytes intact. */ AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, }; enum AVActiveFormatDescription { diff --git a/libavutil/version.h b/libavutil/version.h index ca5d34d681..d257e5438d 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 15 +#define LIBAVUTIL_VERSION_MINOR 16 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From fc40f45b9c070543dc0d7d77b299f2ae619c7acb Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:23 +0100 Subject: [PATCH 688/894] lavfi/showinfo: Support AV_FRAME_DATA_DOVI_METADATA Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_showinfo.c | 108 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 62c7833247..909ad4f8d7 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -27,6 +27,7 @@ #include "libavutil/bswap.h" #include "libavutil/adler32.h" #include "libavutil/display.h" +#include "libavutil/dovi_meta.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/film_grain_params.h" @@ -429,6 +430,110 @@ static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFr } } +static void dump_dovi_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) +{ + const AVDOVIMetadata *dovi = (AVDOVIMetadata *) sd->data; + const AVDOVIRpuDataHeader *hdr = av_dovi_get_header(dovi); + const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); + const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); + + av_log(ctx, AV_LOG_INFO, "Dolby Vision Metadata:\n"); + av_log(ctx, AV_LOG_INFO, " rpu_type=%"PRIu8"; ", hdr->rpu_type); + av_log(ctx, AV_LOG_INFO, "rpu_format=%"PRIu16"; ", hdr->rpu_format); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_profile=%"PRIu8"; ", hdr->vdr_rpu_profile); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_level=%"PRIu8"; ", hdr->vdr_rpu_level); + av_log(ctx, AV_LOG_INFO, "chroma_resampling_explicit_filter_flag=%"PRIu8"; ", hdr->chroma_resampling_explicit_filter_flag); + av_log(ctx, AV_LOG_INFO, "coef_data_type=%"PRIu8"; ", hdr->coef_data_type); + av_log(ctx, AV_LOG_INFO, "coef_log2_denom=%"PRIu8"; ", hdr->coef_log2_denom); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_normalized_idc=%"PRIu8"; ", hdr->vdr_rpu_normalized_idc); + av_log(ctx, AV_LOG_INFO, "bl_video_full_range_flag=%"PRIu8"; ", hdr->bl_video_full_range_flag); + av_log(ctx, AV_LOG_INFO, "bl_bit_depth=%"PRIu8"; ", hdr->bl_bit_depth); + av_log(ctx, AV_LOG_INFO, "el_bit_depth=%"PRIu8"; ", hdr->el_bit_depth); + av_log(ctx, AV_LOG_INFO, "vdr_bit_depth=%"PRIu8"; ", hdr->vdr_bit_depth); + av_log(ctx, AV_LOG_INFO, "spatial_resampling_filter_flag=%"PRIu8"; ", hdr->spatial_resampling_filter_flag); + av_log(ctx, AV_LOG_INFO, "el_spatial_resampling_filter_flag=%"PRIu8"; ", hdr->el_spatial_resampling_filter_flag); + av_log(ctx, AV_LOG_INFO, "disable_residual_flag=%"PRIu8"\n", hdr->disable_residual_flag); + + av_log(ctx, AV_LOG_INFO, " data mapping: "); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_id=%"PRIu8"; ", mapping->vdr_rpu_id); + av_log(ctx, AV_LOG_INFO, "mapping_color_space=%"PRIu8"; ", mapping->mapping_color_space); + av_log(ctx, AV_LOG_INFO, "mapping_chroma_format_idc=%"PRIu8"; ", mapping->mapping_chroma_format_idc); + av_log(ctx, AV_LOG_INFO, "nlq_method_idc=%d; ", (int) mapping->nlq_method_idc); + av_log(ctx, AV_LOG_INFO, "num_x_partitions=%"PRIu32"; ", mapping->num_x_partitions); + av_log(ctx, AV_LOG_INFO, "num_y_partitions=%"PRIu32"\n", mapping->num_y_partitions); + + for (int c = 0; c < 3; c++) { + const AVDOVIReshapingCurve *curve = &mapping->curves[c]; + const AVDOVINLQParams *nlq = &mapping->nlq[c]; + av_log(ctx, AV_LOG_INFO, " channel %d: ", c); + av_log(ctx, AV_LOG_INFO, "pivots={ "); + for (int i = 0; i < curve->num_pivots; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIu16" ", curve->pivots[i]); + av_log(ctx, AV_LOG_INFO, "}; mapping_idc={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%d ", (int) curve->mapping_idc[i]); + av_log(ctx, AV_LOG_INFO, "}; poly_order={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->poly_order[i]); + av_log(ctx, AV_LOG_INFO, "}; poly_coef={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) { + av_log(ctx, AV_LOG_INFO, "{%"PRIi64", %"PRIi64", %"PRIi64"} ", + curve->poly_coef[i][0], + curve->poly_coef[i][1], + curve->poly_coef[i][2]); + } + + av_log(ctx, AV_LOG_INFO, "}; mmr_order={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->mmr_order[i]); + av_log(ctx, AV_LOG_INFO, "}; mmr_constant={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_constant[i]); + av_log(ctx, AV_LOG_INFO, "}; mmr_coef={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) { + av_log(ctx, AV_LOG_INFO, "{"); + for (int j = 0; j < curve->mmr_order[i]; j++) { + for (int k = 0; k < 7; k++) + av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_coef[i][j][k]); + } + av_log(ctx, AV_LOG_INFO, "} "); + } + + av_log(ctx, AV_LOG_INFO, "}; nlq_offset=%"PRIu64"; ", nlq->nlq_offset); + av_log(ctx, AV_LOG_INFO, "vdr_in_max=%"PRIu64"; ", nlq->vdr_in_max); + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + av_log(ctx, AV_LOG_INFO, "linear_deadzone_slope=%"PRIu64"; ", nlq->linear_deadzone_slope); + av_log(ctx, AV_LOG_INFO, "linear_deadzone_threshold=%"PRIu64"\n", nlq->linear_deadzone_threshold); + break; + } + } + + av_log(ctx, AV_LOG_INFO, " color metadata: "); + av_log(ctx, AV_LOG_INFO, "dm_metadata_id=%"PRIu8"; ", color->dm_metadata_id); + av_log(ctx, AV_LOG_INFO, "scene_refresh_flag=%"PRIu8"; ", color->scene_refresh_flag); + av_log(ctx, AV_LOG_INFO, "ycc_to_rgb_matrix={ "); + for (int i = 0; i < 9; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_matrix[i])); + av_log(ctx, AV_LOG_INFO, "}; ycc_to_rgb_offset={ "); + for (int i = 0; i < 3; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_offset[i])); + av_log(ctx, AV_LOG_INFO, "}; rgb_to_lms_matrix={ "); + for (int i = 0; i < 9; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->rgb_to_lms_matrix[i])); + av_log(ctx, AV_LOG_INFO, "}; signal_eotf=%"PRIu16"; ", color->signal_eotf); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param0=%"PRIu16"; ", color->signal_eotf_param0); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param1=%"PRIu16"; ", color->signal_eotf_param1); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param2=%"PRIu32"; ", color->signal_eotf_param2); + av_log(ctx, AV_LOG_INFO, "signal_bit_depth=%"PRIu8"; ", color->signal_bit_depth); + av_log(ctx, AV_LOG_INFO, "signal_color_space=%"PRIu8"; ", color->signal_color_space); + av_log(ctx, AV_LOG_INFO, "signal_chroma_format=%"PRIu8"; ", color->signal_chroma_format); + av_log(ctx, AV_LOG_INFO, "signal_full_range_flag=%"PRIu8"; ", color->signal_full_range_flag); + av_log(ctx, AV_LOG_INFO, "source_min_pq=%"PRIu16"; ", color->source_min_pq); + av_log(ctx, AV_LOG_INFO, "source_max_pq=%"PRIu16"; ", color->source_max_pq); + av_log(ctx, AV_LOG_INFO, "source_diagonal=%"PRIu16"; ", color->source_diagonal); +} + static void dump_color_property(AVFilterContext *ctx, AVFrame *frame) { const char *color_range_str = av_color_range_name(frame->color_range); @@ -617,6 +722,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_FILM_GRAIN_PARAMS: dump_sei_film_grain_params_metadata(ctx, sd); break; + case AV_FRAME_DATA_DOVI_METADATA: + dump_dovi_metadata(ctx, sd); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d " "(%"SIZE_SPECIFIER" bytes)\n", sd->type, sd->size); From a3f41483194b9fc5a6d0fa258e0352236ba97d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Mon, 3 Jan 2022 01:27:24 +0100 Subject: [PATCH 689/894] ffprobe: Support AV_FRAME_DATA_DOVI_METADATA Co-authored-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- fftools/ffprobe.c | 173 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 3 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 906bb03b16..20582ca7ac 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -175,6 +175,10 @@ typedef enum { SECTION_ID_FRAME_SIDE_DATA, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_TIMECODE, + SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, + SECTION_ID_FRAME_SIDE_DATA_COMPONENT, + SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, + SECTION_ID_FRAME_SIDE_DATA_PIECE, SECTION_ID_FRAME_LOG, SECTION_ID_FRAME_LOGS, SECTION_ID_LIBRARY_VERSION, @@ -219,9 +223,13 @@ static struct section sections[] = { [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } }, [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" }, [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" }, - [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, -1 } }, - [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } }, - [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } }, + [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", 0, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "section", 0, { -1 } }, [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } }, [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, }, [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } }, @@ -1809,6 +1817,16 @@ static void writer_register_all(void) writer_print_string(w, k, pbuf.str, 0); \ } while (0) +#define print_list_fmt(k, f, n, ...) do { \ + av_bprint_clear(&pbuf); \ + for (int idx = 0; idx < n; idx++) { \ + if (idx > 0) \ + av_bprint_chars(&pbuf, ' ', 1); \ + av_bprintf(&pbuf, f, __VA_ARGS__); \ + } \ + writer_print_string(w, k, pbuf.str, 0); \ +} while (0) + #define print_int(k, v) writer_print_integer(w, k, v) #define print_q(k, v, s) writer_print_rational(w, k, v, s) #define print_str(k, v) writer_print_string(w, k, v, 0) @@ -1854,6 +1872,153 @@ static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id return ret; } +static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi) +{ + if (!dovi) + return; + + { + const AVDOVIRpuDataHeader *hdr = av_dovi_get_header(dovi); + const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); + const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); + AVBPrint pbuf; + + av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED); + + // header + print_int("rpu_type", hdr->rpu_type); + print_int("rpu_format", hdr->rpu_format); + print_int("vdr_rpu_profile", hdr->vdr_rpu_profile); + print_int("vdr_rpu_level", hdr->vdr_rpu_level); + print_int("chroma_resampling_explicit_filter_flag", + hdr->chroma_resampling_explicit_filter_flag); + print_int("coef_data_type", hdr->coef_data_type); + print_int("coef_log2_denom", hdr->coef_log2_denom); + print_int("vdr_rpu_normalized_idc", hdr->vdr_rpu_normalized_idc); + print_int("bl_video_full_range_flag", hdr->bl_video_full_range_flag); + print_int("bl_bit_depth", hdr->bl_bit_depth); + print_int("el_bit_depth", hdr->el_bit_depth); + print_int("vdr_bit_depth", hdr->vdr_bit_depth); + print_int("spatial_resampling_filter_flag", + hdr->spatial_resampling_filter_flag); + print_int("el_spatial_resampling_filter_flag", + hdr->el_spatial_resampling_filter_flag); + print_int("disable_residual_flag", hdr->disable_residual_flag); + + // data mapping values + print_int("vdr_rpu_id", mapping->vdr_rpu_id); + print_int("mapping_color_space", mapping->mapping_color_space); + print_int("mapping_chroma_format_idc", + mapping->mapping_chroma_format_idc); + + print_int("nlq_method_idc", mapping->nlq_method_idc); + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_NONE: + print_str("nlq_method_idc_name", "none"); + break; + case AV_DOVI_NLQ_LINEAR_DZ: + print_str("nlq_method_idc_name", "linear_dz"); + break; + default: + print_str("nlq_method_idc_name", "unknown"); + break; + } + + print_int("num_x_partitions", mapping->num_x_partitions); + print_int("num_y_partitions", mapping->num_y_partitions); + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST); + + for (int c = 0; c < 3; c++) { + const AVDOVIReshapingCurve *curve = &mapping->curves[c]; + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT); + + print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, curve->pivots[idx]); + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST); + for (int i = 0; i < curve->num_pivots - 1; i++) { + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE); + print_int("mapping_idc", curve->mapping_idc[i]); + switch (curve->mapping_idc[i]) { + case AV_DOVI_MAPPING_POLYNOMIAL: + print_str("mapping_idc_name", "polynomial"); + print_int("poly_order", curve->poly_order[i]); + print_list_fmt("poly_coef", "%"PRIi64, + curve->poly_order[i] + 1, + curve->poly_coef[i][idx]); + break; + case AV_DOVI_MAPPING_MMR: + print_str("mapping_idc_name", "mmr"); + print_int("mmr_order", curve->mmr_order[i]); + print_int("mmr_constant", curve->mmr_constant[i]); + print_list_fmt("mmr_coef", "%"PRIi64, + curve->mmr_order[i] * 7, + curve->mmr_coef[i][0][idx]); + break; + default: + print_str("mapping_idc_name", "unknown"); + break; + } + + // SECTION_ID_FRAME_SIDE_DATA_PIECE + writer_print_section_footer(w); + } + + // SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST + writer_print_section_footer(w); + + if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) { + const AVDOVINLQParams *nlq = &mapping->nlq[c]; + print_int("nlq_offset", nlq->nlq_offset); + print_int("vdr_in_max", nlq->vdr_in_max); + + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + print_int("linear_deadzone_slope", nlq->linear_deadzone_slope); + print_int("linear_deadzone_threshold", nlq->linear_deadzone_threshold); + break; + } + } + + // SECTION_ID_FRAME_SIDE_DATA_COMPONENT + writer_print_section_footer(w); + } + + // SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST + writer_print_section_footer(w); + + // color metadata + print_int("dm_metadata_id", color->dm_metadata_id); + print_int("scene_refresh_flag", color->scene_refresh_flag); + print_list_fmt("ycc_to_rgb_matrix", "%d/%d", + FF_ARRAY_ELEMS(color->ycc_to_rgb_matrix), + color->ycc_to_rgb_matrix[idx].num, + color->ycc_to_rgb_matrix[idx].den); + print_list_fmt("ycc_to_rgb_offset", "%d/%d", + FF_ARRAY_ELEMS(color->ycc_to_rgb_offset), + color->ycc_to_rgb_offset[idx].num, + color->ycc_to_rgb_offset[idx].den); + print_list_fmt("rgb_to_lms_matrix", "%d/%d", + FF_ARRAY_ELEMS(color->rgb_to_lms_matrix), + color->rgb_to_lms_matrix[idx].num, + color->rgb_to_lms_matrix[idx].den); + print_int("signal_eotf", color->signal_eotf); + print_int("signal_eotf_param0", color->signal_eotf_param0); + print_int("signal_eotf_param1", color->signal_eotf_param1); + print_int("signal_eotf_param2", color->signal_eotf_param2); + print_int("signal_bit_depth", color->signal_bit_depth); + print_int("signal_color_space", color->signal_color_space); + print_int("signal_chroma_format", color->signal_chroma_format); + print_int("signal_full_range_flag", color->signal_full_range_flag); + print_int("source_min_pq", color->source_min_pq); + print_int("source_max_pq", color->source_max_pq); + print_int("source_diagonal", color->source_diagonal); + + av_bprint_finalize(&pbuf, NULL); + } +} + static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata) { if (!metadata) @@ -2370,6 +2535,8 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, if (tag) print_str(tag->key, tag->value); print_int("size", sd->size); + } else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) { + print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data); } writer_print_section_footer(w); } From fe0403373964f6a5e633eb7adf9aa104cf9d59ff Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:25 +0100 Subject: [PATCH 690/894] lavc: Implement Dolby Vision RPU parsing Based on a mixture of guesswork, partial documentation in patents, and reverse engineering of real-world samples. Confirmed working for all the samples I've thrown at it. Contains some annoying machinery to persist these values in between frames, which is needed in theory even though I've never actually seen a sample that relies on it in practice. May or may not work. Since the distinction matters greatly for parsing the color matrix values, this includes a small helper function to guess the right profile from the RPU itself in case the user has forgotten to forward the dovi configuration record to the decoder. (Which in practice, only ffmpeg.c and ffplay do..) Notable omissions / deviations: - CRC32 verification. This is based on the MPEG2 CRC32 type, which is similar to IEEE CRC32 but apparently different in subtle enough ways that I could not get it to pass verification no matter what parameters I fed to av_crc. It's possible the code needs some changes. - Linear interpolation support. Nothing documents this (beyond its existence) and no samples use it, so impossible to implement. - All of the extension metadata blocks, but these contain values that seem largely congruent with ST2094, HDR10, or other existing forms of side data, so I will defer parsing/attaching them to a future commit. - The patent describes a mechanism for predicting coefficients from previous RPUs, but the bit for the flag whether to use the prediction deltas or signal entirely new coefficients does not seem to be present in actual RPUs, so we ignore this subsystem entirely. - In the patent's spec, the NLQ subsystem also loops over num_nlq_pivots, but even in the patent the number is hard-coded to one iteration rather than signalled. So we only store one set of coefs. Heavily influenced by https://github.com/quietvoid/dovi_tool Documentation drawn from US Patent 10,701,399 B2 and ETSI GS CCM 001 Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/dovi_rpu.c | 449 ++++++++++++++++++++++++++++++++++++++++++ libavcodec/dovi_rpu.h | 87 ++++++++ 4 files changed, 539 insertions(+) create mode 100644 libavcodec/dovi_rpu.c create mode 100644 libavcodec/dovi_rpu.h diff --git a/configure b/configure index e16a5f34f6..34878117e7 100755 --- a/configure +++ b/configure @@ -2434,6 +2434,7 @@ CONFIG_EXTRA=" cbs_vp9 dirac_parse dnn + dovi_rpu dvprofile exif faandct @@ -2706,6 +2707,7 @@ cbs_mpeg2_select="cbs" cbs_vp9_select="cbs" dct_select="rdft" dirac_parse_select="golomb" +dovi_rpu_select="golomb" dnn_suggest="libtensorflow libopenvino" dnn_deps="avformat swscale" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 79c4275133..e048a1c377 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -77,6 +77,7 @@ OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o +OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o OBJS-$(CONFIG_FAANDCT) += faandct.o diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c new file mode 100644 index 0000000000..a87562c8a3 --- /dev/null +++ b/libavcodec/dovi_rpu.c @@ -0,0 +1,449 @@ +/* + * Dolby Vision RPU decoder + * + * Copyright (C) 2021 Jan Ekström + * Copyright (C) 2021 Niklas Haas + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/buffer.h" + +#include "dovi_rpu.h" +#include "golomb.h" +#include "get_bits.h" + +enum { + RPU_COEFF_FIXED = 0, + RPU_COEFF_FLOAT = 1, +}; + +/** + * Private contents of vdr_ref. + */ +typedef struct DOVIVdrRef { + AVDOVIDataMapping mapping; + AVDOVIColorMetadata color; +} DOVIVdrRef; + +void ff_dovi_ctx_unref(DOVIContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr_ref); i++) + av_buffer_unref(&s->vdr_ref[i]); + + *s = (DOVIContext) { + .logctx = s->logctx, + }; +} + +void ff_dovi_ctx_flush(DOVIContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr_ref); i++) + av_buffer_unref(&s->vdr_ref[i]); + + *s = (DOVIContext) { + .logctx = s->logctx, + .dv_profile = s->dv_profile, + }; +} + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0) +{ + int ret; + s->logctx = s0->logctx; + s->mapping = s0->mapping; + s->color = s0->color; + s->dv_profile = s0->dv_profile; + for (int i = 0; i < DOVI_MAX_DM_ID; i++) { + if ((ret = av_buffer_replace(&s->vdr_ref[i], s0->vdr_ref[i])) < 0) + goto fail; + } + + return 0; + +fail: + ff_dovi_ctx_unref(s); + return ret; +} + +void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord *cfg) +{ + if (!cfg) + return; + + s->dv_profile = cfg->dv_profile; +} + +int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame) +{ + AVFrameSideData *sd; + AVBufferRef *buf; + AVDOVIMetadata *dovi; + size_t dovi_size; + + if (!s->mapping || !s->color) + return 0; /* incomplete dovi metadata */ + + dovi = av_dovi_metadata_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + buf = av_buffer_create((uint8_t *) dovi, dovi_size, NULL, NULL, 0); + if (!buf) { + av_free(dovi); + return AVERROR(ENOMEM); + } + + sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOVI_METADATA, buf); + if (!sd) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + + /* Copy only the parts of these structs known to us at compiler-time. */ +#define COPY(t, a, b, last) memcpy(a, b, offsetof(t, last) + sizeof((b)->last)) + COPY(AVDOVIRpuDataHeader, av_dovi_get_header(dovi), &s->header, disable_residual_flag); + COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq[2].linear_deadzone_threshold); + COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal); + return 0; +} + +static int guess_profile(const AVDOVIRpuDataHeader *hdr) +{ + switch (hdr->vdr_rpu_profile) { + case 0: + if (hdr->bl_video_full_range_flag) + return 5; + break; + case 1: + if (hdr->el_spatial_resampling_filter_flag && !hdr->disable_residual_flag) { + if (hdr->vdr_bit_depth == 12) { + return 7; + } else { + return 4; + } + } else { + return 8; + } + } + + return 0; /* unknown */ +} + +static inline uint64_t get_ue_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr) +{ + uint64_t ipart; + union { uint32_t u32; float f32; } fpart; + + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + ipart = get_ue_golomb_long(gb); + fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom); + return (ipart << hdr->coef_log2_denom) + fpart.u32; + + case RPU_COEFF_FLOAT: + fpart.u32 = get_bits_long(gb, 32); + return fpart.f32 * (1 << hdr->coef_log2_denom); + } + + return 0; /* unreachable */ +} + +static inline int64_t get_se_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr) +{ + int64_t ipart; + union { uint32_t u32; float f32; } fpart; + + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + ipart = get_se_golomb_long(gb); + fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom); + return (ipart << hdr->coef_log2_denom) + fpart.u32; + + case RPU_COEFF_FLOAT: + fpart.u32 = get_bits_long(gb, 32); + return fpart.f32 * (1 << hdr->coef_log2_denom); + } + + return 0; /* unreachable */ +} + +#define VALIDATE(VAR, MIN, MAX) \ + do { \ + if (VAR < MIN || VAR > MAX) { \ + av_log(s->logctx, AV_LOG_ERROR, "RPU validation failed: " \ + #MIN" <= "#VAR" = %d <= "#MAX"\n", (int) VAR); \ + goto fail; \ + } \ + } while (0) + +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) +{ + AVDOVIRpuDataHeader *hdr = &s->header; + GetBitContext *gb = &(GetBitContext){0}; + DOVIVdrRef *vdr; + int ret; + + uint8_t nal_prefix; + uint8_t rpu_type; + uint8_t vdr_seq_info_present; + uint8_t vdr_dm_metadata_present; + uint8_t use_prev_vdr_rpu; + uint8_t use_nlq; + uint8_t profile; + if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) + return ret; + + /* RPU header, common values */ + nal_prefix = get_bits(gb, 8); + VALIDATE(nal_prefix, 25, 25); + rpu_type = get_bits(gb, 6); + if (rpu_type != 2) { + av_log(s->logctx, AV_LOG_WARNING, "Unrecognized RPU type " + "%"PRIu8", ignoring\n", rpu_type); + return 0; + } + + hdr->rpu_type = rpu_type; + hdr->rpu_format = get_bits(gb, 11); + + /* Values specific to RPU type 2 */ + hdr->vdr_rpu_profile = get_bits(gb, 4); + hdr->vdr_rpu_level = get_bits(gb, 4); + + vdr_seq_info_present = get_bits1(gb); + if (vdr_seq_info_present) { + hdr->chroma_resampling_explicit_filter_flag = get_bits1(gb); + hdr->coef_data_type = get_bits(gb, 2); + VALIDATE(hdr->coef_data_type, RPU_COEFF_FIXED, RPU_COEFF_FLOAT); + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + hdr->coef_log2_denom = get_ue_golomb(gb); + VALIDATE(hdr->coef_log2_denom, 13, 32); + break; + case RPU_COEFF_FLOAT: + hdr->coef_log2_denom = 32; /* arbitrary, choose maximum precision */ + break; + } + + hdr->vdr_rpu_normalized_idc = get_bits(gb, 2); + hdr->bl_video_full_range_flag = get_bits1(gb); + + if ((hdr->rpu_format & 0x700) == 0) { + int bl_bit_depth_minus8 = get_ue_golomb_31(gb); + int el_bit_depth_minus8 = get_ue_golomb_31(gb); + int vdr_bit_depth_minus8 = get_ue_golomb_31(gb); + VALIDATE(bl_bit_depth_minus8, 0, 8); + VALIDATE(el_bit_depth_minus8, 0, 8); + VALIDATE(vdr_bit_depth_minus8, 0, 8); + hdr->bl_bit_depth = bl_bit_depth_minus8 + 8; + hdr->el_bit_depth = el_bit_depth_minus8 + 8; + hdr->vdr_bit_depth = vdr_bit_depth_minus8 + 8; + hdr->spatial_resampling_filter_flag = get_bits1(gb); + skip_bits(gb, 3); /* reserved_zero_3bits */ + hdr->el_spatial_resampling_filter_flag = get_bits1(gb); + hdr->disable_residual_flag = get_bits1(gb); + } + } + + if (!hdr->bl_bit_depth) { + av_log(s->logctx, AV_LOG_ERROR, "Missing RPU VDR sequence info?\n"); + goto fail; + } + + vdr_dm_metadata_present = get_bits1(gb); + use_prev_vdr_rpu = get_bits1(gb); + use_nlq = (hdr->rpu_format & 0x700) == 0 && !hdr->disable_residual_flag; + + profile = s->dv_profile ? s->dv_profile : guess_profile(hdr); + if (profile == 5 && use_nlq) { + av_log(s->logctx, AV_LOG_ERROR, "Profile 5 RPUs should not use NLQ\n"); + goto fail; + } + + if (use_prev_vdr_rpu) { + int prev_vdr_rpu_id = get_ue_golomb_31(gb); + VALIDATE(prev_vdr_rpu_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[prev_vdr_rpu_id]) { + av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU ID: %u\n", + prev_vdr_rpu_id); + goto fail; + } + vdr = (DOVIVdrRef *) s->vdr_ref[prev_vdr_rpu_id]->data; + s->mapping = &vdr->mapping; + } else { + int vdr_rpu_id = get_ue_golomb_31(gb); + VALIDATE(vdr_rpu_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[vdr_rpu_id]) { + s->vdr_ref[vdr_rpu_id] = av_buffer_allocz(sizeof(DOVIVdrRef)); + if (!s->vdr_ref[vdr_rpu_id]) + return AVERROR(ENOMEM); + } + + vdr = (DOVIVdrRef *) s->vdr_ref[vdr_rpu_id]->data; + s->mapping = &vdr->mapping; + + vdr->mapping.vdr_rpu_id = vdr_rpu_id; + vdr->mapping.mapping_color_space = get_ue_golomb_31(gb); + vdr->mapping.mapping_chroma_format_idc = get_ue_golomb_31(gb); + + for (int c = 0; c < 3; c++) { + AVDOVIReshapingCurve *curve = &vdr->mapping.curves[c]; + int num_pivots_minus_2 = get_ue_golomb_31(gb); + int pivot = 0; + + VALIDATE(num_pivots_minus_2, 0, AV_DOVI_MAX_PIECES - 1); + curve->num_pivots = num_pivots_minus_2 + 2; + for (int i = 0; i < curve->num_pivots; i++) { + pivot += get_bits(gb, hdr->bl_bit_depth); + curve->pivots[i] = av_clip_uint16(pivot); + } + } + + if (use_nlq) { + vdr->mapping.nlq_method_idc = get_bits(gb, 3); + /** + * The patent mentions another legal value, NLQ_MU_LAW, but it's + * not documented anywhere how to parse or apply that type of NLQ. + */ + VALIDATE(vdr->mapping.nlq_method_idc, 0, AV_DOVI_NLQ_LINEAR_DZ); + } else { + vdr->mapping.nlq_method_idc = AV_DOVI_NLQ_NONE; + } + + vdr->mapping.num_x_partitions = get_ue_golomb_long(gb) + 1; + vdr->mapping.num_y_partitions = get_ue_golomb_long(gb) + 1; + /* End of rpu_data_header(), start of vdr_rpu_data_payload() */ + + for (int c = 0; c < 3; c++) { + AVDOVIReshapingCurve *curve = &vdr->mapping.curves[c]; + for (int i = 0; i < curve->num_pivots - 1; i++) { + int mapping_idc = get_ue_golomb_31(gb); + VALIDATE(mapping_idc, 0, 1); + curve->mapping_idc[i] = mapping_idc; + switch (mapping_idc) { + case AV_DOVI_MAPPING_POLYNOMIAL: { + int poly_order_minus1 = get_ue_golomb_31(gb); + VALIDATE(poly_order_minus1, 0, 1); + curve->poly_order[i] = poly_order_minus1 + 1; + if (poly_order_minus1 == 0) { + int linear_interp_flag = get_bits1(gb); + if (linear_interp_flag) { + /* lack of documentation/samples */ + avpriv_request_sample(s->logctx, "Dolby Vision " + "linear interpolation"); + ff_dovi_ctx_unref(s); + return AVERROR_PATCHWELCOME; + } + } + for (int k = 0; k <= curve->poly_order[i]; k++) + curve->poly_coef[i][k] = get_se_coef(gb, hdr); + break; + } + case AV_DOVI_MAPPING_MMR: { + int mmr_order_minus1 = get_bits(gb, 2); + VALIDATE(mmr_order_minus1, 0, 2); + curve->mmr_order[i] = mmr_order_minus1 + 1; + curve->mmr_constant[i] = get_se_coef(gb, hdr); + for (int j = 0; j < curve->mmr_order[i]; j++) { + for (int k = 0; k < 7; k++) + curve->mmr_coef[i][j][k] = get_se_coef(gb, hdr); + } + break; + } + } + } + } + + if (use_nlq) { + for (int c = 0; c < 3; c++) { + AVDOVINLQParams *nlq = &vdr->mapping.nlq[c]; + nlq->nlq_offset = get_bits(gb, hdr->el_bit_depth); + nlq->vdr_in_max = get_ue_coef(gb, hdr); + switch (vdr->mapping.nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + nlq->linear_deadzone_slope = get_ue_coef(gb, hdr); + nlq->linear_deadzone_threshold = get_ue_coef(gb, hdr); + break; + } + } + } + } + + if (vdr_dm_metadata_present) { + AVDOVIColorMetadata *color; + int affected_dm_id = get_ue_golomb_31(gb); + int current_dm_id = get_ue_golomb_31(gb); + VALIDATE(affected_dm_id, 0, DOVI_MAX_DM_ID); + VALIDATE(current_dm_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[affected_dm_id]) { + s->vdr_ref[affected_dm_id] = av_buffer_allocz(sizeof(DOVIVdrRef)); + if (!s->vdr_ref[affected_dm_id]) + return AVERROR(ENOMEM); + } + + if (!s->vdr_ref[current_dm_id]) { + av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU DM ID: %u\n", + current_dm_id); + goto fail; + } + + /* Update current pointer based on current_dm_id */ + vdr = (DOVIVdrRef *) s->vdr_ref[current_dm_id]->data; + s->color = &vdr->color; + + /* Update values of affected_dm_id */ + vdr = (DOVIVdrRef *) s->vdr_ref[affected_dm_id]->data; + color = &vdr->color; + color->dm_metadata_id = affected_dm_id; + color->scene_refresh_flag = get_ue_golomb_31(gb); + for (int i = 0; i < 9; i++) + color->ycc_to_rgb_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 13); + for (int i = 0; i < 3; i++) { + int denom = profile == 4 ? (1 << 30) : (1 << 28); + unsigned offset = get_bits_long(gb, 32); + if (offset > INT_MAX) { + /* Ensure the result fits inside AVRational */ + offset >>= 1; + denom >>= 1; + } + color->ycc_to_rgb_offset[i] = av_make_q(offset, denom); + } + for (int i = 0; i < 9; i++) + color->rgb_to_lms_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 14); + + color->signal_eotf = get_bits(gb, 16); + color->signal_eotf_param0 = get_bits(gb, 16); + color->signal_eotf_param1 = get_bits(gb, 16); + color->signal_eotf_param2 = get_bits_long(gb, 32); + color->signal_bit_depth = get_bits(gb, 5); + VALIDATE(color->signal_bit_depth, 8, 16); + color->signal_color_space = get_bits(gb, 2); + color->signal_chroma_format = get_bits(gb, 2); + color->signal_full_range_flag = get_bits(gb, 2); + color->source_min_pq = get_bits(gb, 12); + color->source_max_pq = get_bits(gb, 12); + color->source_diagonal = get_bits(gb, 10); + } + + /* FIXME: verify CRC32, requires implementation of AV_CRC_32_MPEG_2 */ + return 0; + +fail: + ff_dovi_ctx_unref(s); /* don't leak potentially invalid state */ + return AVERROR(EINVAL); +} diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h new file mode 100644 index 0000000000..f6ca5bbbc5 --- /dev/null +++ b/libavcodec/dovi_rpu.h @@ -0,0 +1,87 @@ +/* + * Dolby Vision RPU decoder + * + * Copyright (C) 2021 Jan Ekström + * Copyright (C) 2021 Niklas Haas + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DOVI_RPU_H +#define AVCODEC_DOVI_RPU_H + +#include "libavutil/dovi_meta.h" +#include "libavutil/frame.h" + +#define DOVI_MAX_DM_ID 15 +typedef struct DOVIContext { + void *logctx; + + /** + * Currently active RPU data header, updates on every dovi_rpu_parse(). + */ + AVDOVIRpuDataHeader header; + + /** + * Currently active data mappings, or NULL. Points into memory owned by the + * corresponding rpu/vdr_ref, which becomes invalid on the next call to + * dovi_rpu_parse. + */ + const AVDOVIDataMapping *mapping; + const AVDOVIColorMetadata *color; + + /** + * Private fields internal to dovi_rpu.c + */ + AVBufferRef *vdr_ref[DOVI_MAX_DM_ID+1]; + uint8_t dv_profile; + +} DOVIContext; + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0); + +/** + * Completely reset a DOVIContext, preserving only logctx. + */ +void ff_dovi_ctx_unref(DOVIContext *s); + +/** + * Partially reset the internal state. Resets per-frame state while preserving + * fields parsed from the configuration record. + */ +void ff_dovi_ctx_flush(DOVIContext *s); + +/** + * Read the contents of an AVDOVIDecoderConfigurationRecord (usually provided + * by stream side data) and update internal state accordingly. + */ +void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord *cfg); + +/** + * Parse the contents of a Dovi RPU NAL and update the parsed values in the + * DOVIContext struct. + * + * Returns 0 or an error code. + */ +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size); + +/** + * Attach the decoded AVDOVIMetadata as side data to an AVFrame. + */ +int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame); + +#endif /* AVCODEC_DOVI_RPU_H */ From 08d151884b8290cb7d31000565c257ae886ba375 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:26 +0100 Subject: [PATCH 691/894] fate: Limit Dolby Vision RPU test frame count To avoid the ref for this growing to a very large size when attaching the parsed RPU side data. Since this sample does not have any dynamic metadata, two frames will serve just as well as 100. Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- tests/fate/hevc.mak | 2 +- tests/ref/fate/hevc-dv-rpu | 499 ------------------------------------- 2 files changed, 1 insertion(+), 500 deletions(-) diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 6528df6e27..f294cff414 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -273,7 +273,7 @@ FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-monochrome-crop fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-hdr10-plus-metadata -fate-hevc-dv-rpu: CMD = probeframes -show_entries frame=side_data_list -select_streams 0 $(TARGET_SAMPLES)/hevc/dv84.mov +fate-hevc-dv-rpu: CMD = probeframes -show_entries frame=side_data_list -select_streams 0 -read_intervals "%+\#2" $(TARGET_SAMPLES)/hevc/dv84.mov FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-dv-rpu fate-hevc-two-first-slice: CMD = threads=2 framemd5 -i $(TARGET_SAMPLES)/hevc/two_first_slice.mp4 -sws_flags bitexact -t 00:02.00 -an diff --git a/tests/ref/fate/hevc-dv-rpu b/tests/ref/fate/hevc-dv-rpu index 37ad9ffec2..416d9c51a6 100644 --- a/tests/ref/fate/hevc-dv-rpu +++ b/tests/ref/fate/hevc-dv-rpu @@ -11,502 +11,3 @@ side_data_type=Dolby Vision RPU Data side_data_type=Dolby Vision RPU Data [/SIDE_DATA] [/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=H.26[45] User Data Unregistered SEI message -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=H.26[45] User Data Unregistered SEI message -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=H.26[45] User Data Unregistered SEI message -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] From a538df7eab19ecd0e2d59ef13a84e343de7f65b7 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:27 +0100 Subject: [PATCH 692/894] lavc/hevcdec: Parse DOVI RPU NALs And expose the parsed values as frame side data. Update FATE results to match. It's worth documenting that this relies on the dovi configuration record being present on the first AVPacket fed to the decoder, which in practice is the case if if the API user has called something like av_format_inject_global_side_data, which is unfortunately not the default. This commit is not the time and place to change that behavior, though. Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- configure | 2 +- libavcodec/hevcdec.c | 37 ++++-- libavcodec/hevcdec.h | 2 + tests/ref/fate/hevc-dv-rpu | 224 +++++++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 34878117e7..50aa0d596d 100755 --- a/configure +++ b/configure @@ -2826,7 +2826,7 @@ h264_decoder_suggest="error_resilience" hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" -hevc_decoder_select="atsc_a53 bswapdsp cabac golomb hevcparse videodsp" +hevc_decoder_select="atsc_a53 bswapdsp cabac dovi_rpu golomb hevcparse videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" hymt_decoder_select="huffyuv_decoder" diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 3aa70e2245..8d7a4f7147 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2723,6 +2723,7 @@ error: static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; + int ret; if (s->sei.frame_packing.present && s->sei.frame_packing.arrangement_type >= 3 && @@ -2977,6 +2978,9 @@ static int set_side_data(HEVCContext *s) s->rpu_buf = NULL; } + if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) + return ret; + return 0; } @@ -3308,16 +3312,23 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) if (s->pkt.nb_nals > 1 && s->pkt.nals[s->pkt.nb_nals - 1].type == HEVC_NAL_UNSPEC62 && s->pkt.nals[s->pkt.nb_nals - 1].size > 2 && !s->pkt.nals[s->pkt.nb_nals - 1].nuh_layer_id && !s->pkt.nals[s->pkt.nb_nals - 1].temporal_id) { + H2645NAL *nal = &s->pkt.nals[s->pkt.nb_nals - 1]; if (s->rpu_buf) { av_buffer_unref(&s->rpu_buf); av_log(s->avctx, AV_LOG_WARNING, "Multiple Dolby Vision RPUs found in one AU. Skipping previous.\n"); } - s->rpu_buf = av_buffer_alloc(s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); + s->rpu_buf = av_buffer_alloc(nal->raw_size - 2); if (!s->rpu_buf) return AVERROR(ENOMEM); + memcpy(s->rpu_buf->data, nal->raw_data + 2, nal->raw_size - 2); - memcpy(s->rpu_buf->data, s->pkt.nals[s->pkt.nb_nals - 1].raw_data + 2, s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); + ret = ff_dovi_rpu_parse(&s->dovi_ctx, nal->data + 2, nal->size - 2); + if (ret < 0) { + av_buffer_unref(&s->rpu_buf); + av_log(s->avctx, AV_LOG_WARNING, "Error parsing DOVI NAL unit.\n"); + /* ignore */ + } } /* decode the NAL units */ @@ -3450,8 +3461,8 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, AVPacket *avpkt) { int ret; - size_t new_extradata_size; - uint8_t *new_extradata; + uint8_t *sd; + size_t sd_size; HEVCContext *s = avctx->priv_data; if (!avpkt->size) { @@ -3463,14 +3474,17 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, return 0; } - new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, - &new_extradata_size); - if (new_extradata && new_extradata_size > 0) { - ret = hevc_decode_extradata(s, new_extradata, new_extradata_size, 0); + sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &sd_size); + if (sd && sd_size > 0) { + ret = hevc_decode_extradata(s, sd, sd_size, 0); if (ret < 0) return ret; } + sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_DOVI_CONF, &sd_size); + if (sd && sd_size > 0) + ff_dovi_update_cfg(&s->dovi_ctx, (AVDOVIDecoderConfigurationRecord *) sd); + s->ref = NULL; ret = decode_nal_units(s, avpkt->data, avpkt->size); if (ret < 0) @@ -3563,6 +3577,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) pic_arrays_free(s); + ff_dovi_ctx_unref(&s->dovi_ctx); av_buffer_unref(&s->rpu_buf); av_freep(&s->md5_ctx); @@ -3647,6 +3662,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ff_bswapdsp_init(&s->bdsp); + s->dovi_ctx.logctx = avctx; s->context_initialized = 1; s->eos = 0; @@ -3755,6 +3771,10 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (ret < 0) return ret; + ret = ff_dovi_ctx_replace(&s->dovi_ctx, &s0->dovi_ctx); + if (ret < 0) + return ret; + s->sei.frame_packing = s0->sei.frame_packing; s->sei.display_orientation = s0->sei.display_orientation; s->sei.mastering_display = s0->sei.mastering_display; @@ -3811,6 +3831,7 @@ static void hevc_decode_flush(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; ff_hevc_flush_dpb(s); ff_hevc_reset_sei(&s->sei); + ff_dovi_ctx_flush(&s->dovi_ctx); av_buffer_unref(&s->rpu_buf); s->max_ra = INT_MAX; s->eos = 1; diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 870ff178d4..157bc6926f 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -32,6 +32,7 @@ #include "avcodec.h" #include "bswapdsp.h" #include "cabac.h" +#include "dovi_rpu.h" #include "get_bits.h" #include "hevcpred.h" #include "h2645_parse.h" @@ -574,6 +575,7 @@ typedef struct HEVCContext { int nuh_layer_id; AVBufferRef *rpu_buf; ///< 0 or 1 Dolby Vision RPUs. + DOVIContext dovi_ctx; ///< Dolby Vision decoding context } HEVCContext; /** diff --git a/tests/ref/fate/hevc-dv-rpu b/tests/ref/fate/hevc-dv-rpu index 416d9c51a6..1980ab13ea 100644 --- a/tests/ref/fate/hevc-dv-rpu +++ b/tests/ref/fate/hevc-dv-rpu @@ -5,9 +5,233 @@ side_data_type=H.26[45] User Data Unregistered SEI message [SIDE_DATA] side_data_type=Dolby Vision RPU Data [/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision Metadata +rpu_type=2 +rpu_format=18 +vdr_rpu_profile=1 +vdr_rpu_level=0 +chroma_resampling_explicit_filter_flag=0 +coef_data_type=0 +coef_log2_denom=23 +vdr_rpu_normalized_idc=1 +bl_video_full_range_flag=0 +bl_bit_depth=10 +el_bit_depth=10 +vdr_bit_depth=12 +spatial_resampling_filter_flag=0 +el_spatial_resampling_filter_flag=0 +disable_residual_flag=1 +vdr_rpu_id=0 +mapping_color_space=0 +mapping_chroma_format_idc=0 +nlq_method_idc=-1 +nlq_method_idc_name=none +num_x_partitions=1 +num_y_partitions=1 +[COMPONENT] +pivots=63 132 362 618 874 911 927 935 942 +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-409680 16721463 -20276640 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-119056 13575212 -12867889 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=1317527 5338528 -948122 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=2119979 2065496 2288524 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=7982780 -11367226 9973944 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=53792084 -114243184 67724328 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=112973872 -244837568 139764480 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=236828416 -518849056 291306944 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-4200453 +mmr_coef=9094176 31944476 739652 -27103344 -3431599 -11015088 22758042 -2028643 -30021218 -906885 26272992 7291404 16488745 -78087176 -1487777 12496543 762460 -4281948 -5768035 -7843163 103636960 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-10387889 +mmr_coef=29604202 3214133 46206184 -8564340 -53383996 1628407 5426045 -21634202 -5251953 -50812292 19221972 76726656 -425892 -35041240 5917361 2863974 25030554 -14404292 -41230120 1229046 53575140 +[/SECTION] +[/COMPONENT] +dm_metadata_id=0 +scene_refresh_flag=1 +ycc_to_rgb_matrix=9574/8192 0/8192 13802/8192 9574/8192 -1540/8192 -5348/8192 9574/8192 17610/8192 0/8192 +ycc_to_rgb_offset=16777216/268435456 134217728/268435456 134217728/268435456 +rgb_to_lms_matrix=7222/16384 8771/16384 390/16384 2654/16384 12430/16384 1300/16384 0/16384 422/16384 15962/16384 +signal_eotf=65535 +signal_eotf_param0=0 +signal_eotf_param1=0 +signal_eotf_param2=0 +signal_bit_depth=12 +signal_color_space=0 +signal_chroma_format=0 +signal_full_range_flag=1 +source_min_pq=0 +source_max_pq=3079 +source_diagonal=42 +[/SIDE_DATA] [/FRAME] [FRAME] [SIDE_DATA] side_data_type=Dolby Vision RPU Data [/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision Metadata +rpu_type=2 +rpu_format=18 +vdr_rpu_profile=1 +vdr_rpu_level=0 +chroma_resampling_explicit_filter_flag=0 +coef_data_type=0 +coef_log2_denom=23 +vdr_rpu_normalized_idc=1 +bl_video_full_range_flag=0 +bl_bit_depth=10 +el_bit_depth=10 +vdr_bit_depth=12 +spatial_resampling_filter_flag=0 +el_spatial_resampling_filter_flag=0 +disable_residual_flag=1 +vdr_rpu_id=0 +mapping_color_space=0 +mapping_chroma_format_idc=0 +nlq_method_idc=-1 +nlq_method_idc_name=none +num_x_partitions=1 +num_y_partitions=1 +[COMPONENT] +pivots=63 132 362 618 874 911 927 935 942 +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-409680 16721463 -20276640 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-119056 13575212 -12867889 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=1317527 5338528 -948122 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=2119979 2065496 2288524 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=7982780 -11367226 9973944 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=53792084 -114243184 67724328 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=112973872 -244837568 139764480 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=236828416 -518849056 291306944 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-4200453 +mmr_coef=9094176 31944476 739652 -27103344 -3431599 -11015088 22758042 -2028643 -30021218 -906885 26272992 7291404 16488745 -78087176 -1487777 12496543 762460 -4281948 -5768035 -7843163 103636960 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-10387889 +mmr_coef=29604202 3214133 46206184 -8564340 -53383996 1628407 5426045 -21634202 -5251953 -50812292 19221972 76726656 -425892 -35041240 5917361 2863974 25030554 -14404292 -41230120 1229046 53575140 +[/SECTION] +[/COMPONENT] +dm_metadata_id=0 +scene_refresh_flag=1 +ycc_to_rgb_matrix=9574/8192 0/8192 13802/8192 9574/8192 -1540/8192 -5348/8192 9574/8192 17610/8192 0/8192 +ycc_to_rgb_offset=16777216/268435456 134217728/268435456 134217728/268435456 +rgb_to_lms_matrix=7222/16384 8771/16384 390/16384 2654/16384 12430/16384 1300/16384 0/16384 422/16384 15962/16384 +signal_eotf=65535 +signal_eotf_param0=0 +signal_eotf_param1=0 +signal_eotf_param2=0 +signal_bit_depth=12 +signal_color_space=0 +signal_chroma_format=0 +signal_full_range_flag=1 +source_min_pq=0 +source_max_pq=3079 +source_diagonal=42 +[/SIDE_DATA] [/FRAME] From 9c91930ef799b855bda9fb578fff5949f3bf2525 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 12:40:07 +0100 Subject: [PATCH 693/894] doc/APIchanges: Fill in the commit hash for DOVI metadata addition Signed-off-by: Andreas Rheinhardt --- doc/APIchanges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0fb3f1e3d7..8df0364e4c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,7 +14,7 @@ libavutil: 2021-04-27 API changes, most recent first: -2022-01-04 - xxxxxxxxxx - lavu 57.16.100 - frame.h +2022-01-04 - 78dc21b123e - lavu 57.16.100 - frame.h Add AV_FRAME_DATA_DOVI_METADATA. 2022-01-03 - 70f318e6b6c - lavf 59.13.100 - avformat.h From d1f7700133312929d64aaa69ab3a08b5ae171390 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:36 +0100 Subject: [PATCH 694/894] avdevice/dshow: tv_tuner_audio_dialog cleanup missing Cleanup was missing for when the show_analog_tv_tuner_audio_dialog is true. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow_crossbar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index 2438683cde..961defe690 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -204,5 +204,9 @@ end: IAMTVTuner_Release(tv_tuner_filter); if (tv_tuner_base_filter) IBaseFilter_Release(tv_tuner_base_filter); + if (tv_audio_filter) + IAMAudioInputMixer_Release(tv_audio_filter); + if (tv_audio_base_filter) + IBaseFilter_Release(tv_audio_base_filter); return hr; } From 307d2b867f35cb18f9ff6085f7e5298c3f0be278 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:37 +0100 Subject: [PATCH 695/894] avdevice/dshow: proper cleanup of queried media types Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 30f1be1ead..4b6887881d 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -953,7 +953,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown"); av_log(avctx, AV_LOG_INFO, "\n"); - continue; + goto next; } if (requested_video_codec_id != AV_CODEC_ID_RAWVIDEO) { if (requested_video_codec_id != fmt_info->codec_id) @@ -1038,6 +1038,7 @@ next: if (type && type->pbFormat) CoTaskMemFree(type->pbFormat); CoTaskMemFree(type); + type = NULL; } // previously found a matching VIDEOINFOHEADER format and stored // it for safe keeping. Searching further for a matching From 76e164f3326c3c2330f3fdd22716ca2495e7c612 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:38 +0100 Subject: [PATCH 696/894] avdevice/dshow: fix crash on x86 fix regression introduced in 911ba8417e8881a7380842e69e11ca05fdc46575. Removal of WINAPI decoration from function signatures caused crashed when using dshow on x86. Fixes #9568 Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow_capture.h | 118 ++++++++++++++--------------- libavdevice/dshow_enummediatypes.c | 8 +- libavdevice/dshow_enumpins.c | 8 +- libavdevice/dshow_filter.c | 24 +++--- libavdevice/dshow_pin.c | 48 ++++++------ 5 files changed, 103 insertions(+), 103 deletions(-) diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 5a2691518c..21f5cf7e83 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -70,7 +70,7 @@ enum dshowSourceFilterType { }; #define DECLARE_QUERYINTERFACE(prefix, class, ...) \ -long \ +long WINAPI \ ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \ { \ struct GUIDoffset ifaces[] = __VA_ARGS__; \ @@ -93,14 +93,14 @@ ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObje return E_NOINTERFACE; \ } #define DECLARE_ADDREF(prefix, class) \ -unsigned long \ +unsigned long WINAPI \ ff_dshow_##prefix##_AddRef(class *this) \ { \ dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_AddRef(%p)\t%ld\n", this, this->ref+1); \ return InterlockedIncrement(&this->ref); \ } #define DECLARE_RELEASE(prefix, class) \ -unsigned long \ +unsigned long WINAPI \ ff_dshow_##prefix##_Release(class *this) \ { \ long ref = InterlockedDecrement(&this->ref); \ @@ -167,34 +167,34 @@ struct DShowPin { IMemInputPinVtbl *imemvtbl; }; -long ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **); -unsigned long ff_dshow_pin_AddRef (DShowPin *); -unsigned long ff_dshow_pin_Release (DShowPin *); -long ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_Disconnect (DShowPin *); -long ff_dshow_pin_ConnectedTo (DShowPin *, IPin **); -long ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *); -long ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *); -long ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *); -long ff_dshow_pin_QueryId (DShowPin *, wchar_t **); -long ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **); -long ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *); -long ff_dshow_pin_EndOfStream (DShowPin *); -long ff_dshow_pin_BeginFlush (DShowPin *); -long ff_dshow_pin_EndFlush (DShowPin *); -long ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double); +long WINAPI ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **); +unsigned long WINAPI ff_dshow_pin_AddRef (DShowPin *); +unsigned long WINAPI ff_dshow_pin_Release (DShowPin *); +long WINAPI ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_Disconnect (DShowPin *); +long WINAPI ff_dshow_pin_ConnectedTo (DShowPin *, IPin **); +long WINAPI ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *); +long WINAPI ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *); +long WINAPI ff_dshow_pin_QueryId (DShowPin *, wchar_t **); +long WINAPI ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **); +long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *); +long WINAPI ff_dshow_pin_EndOfStream (DShowPin *); +long WINAPI ff_dshow_pin_BeginFlush (DShowPin *); +long WINAPI ff_dshow_pin_EndFlush (DShowPin *); +long WINAPI ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double); -long ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **); -unsigned long ff_dshow_meminputpin_AddRef (DShowMemInputPin *); -unsigned long ff_dshow_meminputpin_Release (DShowMemInputPin *); -long ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **); -long ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL); -long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *); -long ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *); -long ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *); -long ff_dshow_meminputpin_ReceiveCanBlock (DShowMemInputPin *); +long WINAPI ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **); +unsigned long WINAPI ff_dshow_meminputpin_AddRef (DShowMemInputPin *); +unsigned long WINAPI ff_dshow_meminputpin_Release (DShowMemInputPin *); +long WINAPI ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **); +long WINAPI ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL); +long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *); +long WINAPI ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *); +long WINAPI ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *); +long WINAPI ff_dshow_meminputpin_ReceiveCanBlock (DShowMemInputPin *); void ff_dshow_pin_Destroy(DShowPin *); DShowPin *ff_dshow_pin_Create (DShowFilter *filter); @@ -212,13 +212,13 @@ struct DShowEnumPins { DShowFilter *filter; }; -long ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **); -unsigned long ff_dshow_enumpins_AddRef (DShowEnumPins *); -unsigned long ff_dshow_enumpins_Release (DShowEnumPins *); -long ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *); -long ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long); -long ff_dshow_enumpins_Reset (DShowEnumPins *); -long ff_dshow_enumpins_Clone (DShowEnumPins *, DShowEnumPins **); +long WINAPI ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **); +unsigned long WINAPI ff_dshow_enumpins_AddRef (DShowEnumPins *); +unsigned long WINAPI ff_dshow_enumpins_Release (DShowEnumPins *); +long WINAPI ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *); +long WINAPI ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long); +long WINAPI ff_dshow_enumpins_Reset (DShowEnumPins *); +long WINAPI ff_dshow_enumpins_Clone (DShowEnumPins *, DShowEnumPins **); void ff_dshow_enumpins_Destroy(DShowEnumPins *); DShowEnumPins *ff_dshow_enumpins_Create (DShowPin *pin, DShowFilter *filter); @@ -233,13 +233,13 @@ struct DShowEnumMediaTypes { AM_MEDIA_TYPE type; }; -long ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **); -unsigned long ff_dshow_enummediatypes_AddRef (DShowEnumMediaTypes *); -unsigned long ff_dshow_enummediatypes_Release (DShowEnumMediaTypes *); -long ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); -long ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long); -long ff_dshow_enummediatypes_Reset (DShowEnumMediaTypes *); -long ff_dshow_enummediatypes_Clone (DShowEnumMediaTypes *, DShowEnumMediaTypes **); +long WINAPI ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **); +unsigned long WINAPI ff_dshow_enummediatypes_AddRef (DShowEnumMediaTypes *); +unsigned long WINAPI ff_dshow_enummediatypes_Release (DShowEnumMediaTypes *); +long WINAPI ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); +long WINAPI ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long); +long WINAPI ff_dshow_enummediatypes_Reset (DShowEnumMediaTypes *); +long WINAPI ff_dshow_enummediatypes_Clone (DShowEnumMediaTypes *, DShowEnumMediaTypes **); void ff_dshow_enummediatypes_Destroy(DShowEnumMediaTypes *); DShowEnumMediaTypes *ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type); @@ -262,21 +262,21 @@ struct DShowFilter { void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type); }; -long ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **); -unsigned long ff_dshow_filter_AddRef (DShowFilter *); -unsigned long ff_dshow_filter_Release (DShowFilter *); -long ff_dshow_filter_GetClassID (DShowFilter *, CLSID *); -long ff_dshow_filter_Stop (DShowFilter *); -long ff_dshow_filter_Pause (DShowFilter *); -long ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME); -long ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *); -long ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *); -long ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **); -long ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **); -long ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **); -long ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *); -long ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *); -long ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **); +long WINAPI ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **); +unsigned long WINAPI ff_dshow_filter_AddRef (DShowFilter *); +unsigned long WINAPI ff_dshow_filter_Release (DShowFilter *); +long WINAPI ff_dshow_filter_GetClassID (DShowFilter *, CLSID *); +long WINAPI ff_dshow_filter_Stop (DShowFilter *); +long WINAPI ff_dshow_filter_Pause (DShowFilter *); +long WINAPI ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME); +long WINAPI ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *); +long WINAPI ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *); +long WINAPI ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **); +long WINAPI ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **); +long WINAPI ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **); +long WINAPI ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *); +long WINAPI ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *); +long WINAPI ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **); void ff_dshow_filter_Destroy(DShowFilter *); DShowFilter *ff_dshow_filter_Create (void *, void *, enum dshowDeviceType); diff --git a/libavdevice/dshow_enummediatypes.c b/libavdevice/dshow_enummediatypes.c index 82944507f6..4cb7057e17 100644 --- a/libavdevice/dshow_enummediatypes.c +++ b/libavdevice/dshow_enummediatypes.c @@ -26,7 +26,7 @@ DECLARE_QUERYINTERFACE(enummediatypes, DShowEnumMediaTypes, DECLARE_ADDREF(enummediatypes, DShowEnumMediaTypes) DECLARE_RELEASE(enummediatypes, DShowEnumMediaTypes) -long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, +long WINAPI ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, AM_MEDIA_TYPE **types, unsigned long *fetched) { int count = 0; @@ -50,20 +50,20 @@ long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, return S_FALSE; return S_OK; } -long ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) +long WINAPI ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) { dshowdebug("ff_dshow_enummediatypes_Skip(%p)\n", this); if (n) /* Any skip will always fall outside of the only valid type. */ return S_FALSE; return S_OK; } -long ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) +long WINAPI ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) { dshowdebug("ff_dshow_enummediatypes_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) +long WINAPI ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) { DShowEnumMediaTypes *new; dshowdebug("ff_dshow_enummediatypes_Clone(%p)\n", this); diff --git a/libavdevice/dshow_enumpins.c b/libavdevice/dshow_enumpins.c index 6bf59928f9..759b589ade 100644 --- a/libavdevice/dshow_enumpins.c +++ b/libavdevice/dshow_enumpins.c @@ -26,7 +26,7 @@ DECLARE_QUERYINTERFACE(enumpins, DShowEnumPins, DECLARE_ADDREF(enumpins, DShowEnumPins) DECLARE_RELEASE(enumpins, DShowEnumPins) -long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, +long WINAPI ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, unsigned long *fetched) { int count = 0; @@ -45,20 +45,20 @@ long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, return S_FALSE; return S_OK; } -long ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) +long WINAPI ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) { dshowdebug("ff_dshow_enumpins_Skip(%p)\n", this); if (n) /* Any skip will always fall outside of the only valid pin. */ return S_FALSE; return S_OK; } -long ff_dshow_enumpins_Reset(DShowEnumPins *this) +long WINAPI ff_dshow_enumpins_Reset(DShowEnumPins *this) { dshowdebug("ff_dshow_enumpins_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) +long WINAPI ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) { DShowEnumPins *new; dshowdebug("ff_dshow_enumpins_Clone(%p)\n", this); diff --git a/libavdevice/dshow_filter.c b/libavdevice/dshow_filter.c index 61e057a836..4642ac077c 100644 --- a/libavdevice/dshow_filter.c +++ b/libavdevice/dshow_filter.c @@ -26,32 +26,32 @@ DECLARE_QUERYINTERFACE(filter, DShowFilter, DECLARE_ADDREF(filter, DShowFilter) DECLARE_RELEASE(filter, DShowFilter) -long ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) +long WINAPI ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) { dshowdebug("ff_dshow_filter_GetClassID(%p)\n", this); /* I'm not creating a ClassID just for this. */ return E_FAIL; } -long ff_dshow_filter_Stop(DShowFilter *this) +long WINAPI ff_dshow_filter_Stop(DShowFilter *this) { dshowdebug("ff_dshow_filter_Stop(%p)\n", this); this->state = State_Stopped; return S_OK; } -long ff_dshow_filter_Pause(DShowFilter *this) +long WINAPI ff_dshow_filter_Pause(DShowFilter *this) { dshowdebug("ff_dshow_filter_Pause(%p)\n", this); this->state = State_Paused; return S_OK; } -long ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) +long WINAPI ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) { dshowdebug("ff_dshow_filter_Run(%p) %"PRId64"\n", this, start); this->state = State_Running; this->start_time = start; return S_OK; } -long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) +long WINAPI ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) { dshowdebug("ff_dshow_filter_GetState(%p)\n", this); if (!state) @@ -59,7 +59,7 @@ long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) *state = this->state; return S_OK; } -long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) +long WINAPI ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) { dshowdebug("ff_dshow_filter_SetSyncSource(%p)\n", this); @@ -73,7 +73,7 @@ long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) return S_OK; } -long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) +long WINAPI ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) { dshowdebug("ff_dshow_filter_GetSyncSource(%p)\n", this); @@ -85,7 +85,7 @@ long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) return S_OK; } -long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) +long WINAPI ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) { DShowEnumPins *new; dshowdebug("ff_dshow_filter_EnumPins(%p)\n", this); @@ -99,7 +99,7 @@ long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) *enumpin = (IEnumPins *) new; return S_OK; } -long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) +long WINAPI ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) { DShowPin *found = NULL; dshowdebug("ff_dshow_filter_FindPin(%p)\n", this); @@ -116,7 +116,7 @@ long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) return S_OK; } -long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) +long WINAPI ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) { dshowdebug("ff_dshow_filter_QueryFilterInfo(%p)\n", this); @@ -128,7 +128,7 @@ long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) return S_OK; } -long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, +long WINAPI ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, const wchar_t *name) { dshowdebug("ff_dshow_filter_JoinFilterGraph(%p)\n", this); @@ -139,7 +139,7 @@ long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, return S_OK; } -long ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) +long WINAPI ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) { dshowdebug("ff_dshow_filter_QueryVendorInfo(%p)\n", this); diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 2d1fa0e882..f846b68918 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -29,13 +29,13 @@ DECLARE_QUERYINTERFACE(pin, DShowPin, DECLARE_ADDREF(pin, DShowPin) DECLARE_RELEASE(pin, DShowPin) -long ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_Connect(%p, %p, %p)\n", this, pin, type); /* Input pins receive connections. */ return S_FALSE; } -long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, +long WINAPI ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { enum dshowDeviceType devtype = this->filter->type; @@ -62,7 +62,7 @@ long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, return S_OK; } -long ff_dshow_pin_Disconnect(DShowPin *this) +long WINAPI ff_dshow_pin_Disconnect(DShowPin *this) { dshowdebug("ff_dshow_pin_Disconnect(%p)\n", this); @@ -75,7 +75,7 @@ long ff_dshow_pin_Disconnect(DShowPin *this) return S_OK; } -long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) +long WINAPI ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) { dshowdebug("ff_dshow_pin_ConnectedTo(%p)\n", this); @@ -88,7 +88,7 @@ long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) return S_OK; } -long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_ConnectionMediaType(%p)\n", this); @@ -99,7 +99,7 @@ long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) return ff_copy_dshow_media_type(type, &this->type); } -long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) +long WINAPI ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) { dshowdebug("ff_dshow_pin_QueryPinInfo(%p)\n", this); @@ -115,7 +115,7 @@ long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) return S_OK; } -long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) +long WINAPI ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) { dshowdebug("ff_dshow_pin_QueryDirection(%p)\n", this); if (!dir) @@ -123,7 +123,7 @@ long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) *dir = PINDIR_INPUT; return S_OK; } -long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) +long WINAPI ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) { dshowdebug("ff_dshow_pin_QueryId(%p)\n", this); @@ -134,12 +134,12 @@ long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) return S_OK; } -long ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_QueryAccept(%p)\n", this); return S_FALSE; } -long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) +long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) { const AM_MEDIA_TYPE *type = NULL; DShowEnumMediaTypes *new; @@ -154,31 +154,31 @@ long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) *enumtypes = (IEnumMediaTypes *) new; return S_OK; } -long ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, +long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, unsigned long *npin) { dshowdebug("ff_dshow_pin_QueryInternalConnections(%p)\n", this); return E_NOTIMPL; } -long ff_dshow_pin_EndOfStream(DShowPin *this) +long WINAPI ff_dshow_pin_EndOfStream(DShowPin *this) { dshowdebug("ff_dshow_pin_EndOfStream(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_BeginFlush(DShowPin *this) +long WINAPI ff_dshow_pin_BeginFlush(DShowPin *this) { dshowdebug("ff_dshow_pin_BeginFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_EndFlush(DShowPin *this) +long WINAPI ff_dshow_pin_EndFlush(DShowPin *this) { dshowdebug("ff_dshow_pin_EndFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, +long WINAPI ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { dshowdebug("ff_dshow_pin_NewSegment(%p)\n", this); @@ -250,43 +250,43 @@ DECLARE_DESTROY(pin, DShowPin, ff_dshow_pin_Free) /***************************************************************************** * DShowMemInputPin ****************************************************************************/ -long ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, +long WINAPI ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, void **ppvObject) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_QueryInterface(%p)\n", this); return ff_dshow_pin_QueryInterface(pin, riid, ppvObject); } -unsigned long ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) +unsigned long WINAPI ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_AddRef(%p)\n", this); return ff_dshow_pin_AddRef(pin); } -unsigned long ff_dshow_meminputpin_Release(DShowMemInputPin *this) +unsigned long WINAPI ff_dshow_meminputpin_Release(DShowMemInputPin *this) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_Release(%p)\n", this); return ff_dshow_pin_Release(pin); } -long ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) +long WINAPI ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) { dshowdebug("ff_dshow_meminputpin_GetAllocator(%p)\n", this); return VFW_E_NO_ALLOCATOR; } -long ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, +long WINAPI ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, BOOL rdwr) { dshowdebug("ff_dshow_meminputpin_NotifyAllocator(%p)\n", this); return S_OK; } -long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, +long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, ALLOCATOR_PROPERTIES *props) { dshowdebug("ff_dshow_meminputpin_GetAllocatorRequirements(%p)\n", this); return E_NOTIMPL; } -long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) +long WINAPI ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); enum dshowDeviceType devtype = pin->filter->type; @@ -354,7 +354,7 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) return S_OK; } -long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, +long WINAPI ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, IMediaSample **samples, long n, long *nproc) { int i; @@ -366,7 +366,7 @@ long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, *nproc = n; return S_OK; } -long ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) +long WINAPI ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) { dshowdebug("ff_dshow_meminputpin_ReceiveCanBlock(%p)\n", this); /* I swear I will not block. */ From 25518f2aa6821cd37bb20b53853eb1b2ef95b755 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:39 +0100 Subject: [PATCH 697/894] avdevice/dshow: only set pin format if wanted Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 4b6887881d..f2d95fa470 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1046,7 +1046,7 @@ next: // format based on the VIDEOINFOHEADER format. // NB: this never applies to an audio format because // previous_match_type always NULL in that case - if (!format_set && previous_match_type) { + if (pformat_set && !format_set && previous_match_type) { if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) format_set = 1; } From e84d8ba44141b55f2b28e0ad3b597d2e7d422336 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:40 +0100 Subject: [PATCH 698/894] avdevice/dshow: ensure pin's default format is set Fixes regression in a1c4929f: there apparently are devices out there that expose a pin default format that has parameters outside the capabilities of any of the formats exposed on the pin (sic?). The VirtualCam plugin (v 2.0.5) of OBS-Studio (v 27.1.3) is such a device. Now when a default format was found, but not selected when iterating all formats, fall back to directly setting the default format. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 88 +++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index f2d95fa470..a435ae1807 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -758,6 +758,31 @@ static struct dshow_format_info *dshow_get_format_info(AM_MEDIA_TYPE *type) return fmt_info; } +static void dshow_get_default_format(IPin *pin, IAMStreamConfig *config, enum dshowDeviceType devtype, AM_MEDIA_TYPE **type) +{ + HRESULT hr; + + if ((hr = IAMStreamConfig_GetFormat(config, type)) != S_OK) { + if (hr == E_NOTIMPL || !IsEqualGUID(&(*type)->majortype, devtype == VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + // default not available or of wrong type, + // fall back to iterating exposed formats + // until one of the right type is found + IEnumMediaTypes* types = NULL; + if (IPin_EnumMediaTypes(pin, &types) != S_OK) + return; + IEnumMediaTypes_Reset(types); + while (IEnumMediaTypes_Next(types, 1, type, NULL) == S_OK) { + if (IsEqualGUID(&(*type)->majortype, devtype == VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + break; + } + CoTaskMemFree(*type); + *type = NULL; + } + IEnumMediaTypes_Release(types); + } + } +} + /** * Cycle through available formats available from the specified pin, * try to set parameters specified through AVOptions, or the pin's @@ -813,32 +838,11 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, use_default = !dshow_should_set_format(avctx, devtype); if (use_default && pformat_set) { - HRESULT hr; - // get default - if ((hr = IAMStreamConfig_GetFormat(config, &type)) != S_OK) { - if (hr == E_NOTIMPL || !IsEqualGUID(&type->majortype, devtype==VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { - // default not available or of wrong type, - // fall back to iterating exposed formats - // until one of the right type is found - IEnumMediaTypes *types = NULL; - if (IPin_EnumMediaTypes(pin, &types) != S_OK) - goto end; - IEnumMediaTypes_Reset(types); - while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { - if (IsEqualGUID(&type->majortype, devtype==VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { - break; - } - CoTaskMemFree(type); - type = NULL; - } - IEnumMediaTypes_Release(types); - } - - if (!type) - // this pin does not expose any formats of the expected type - goto end; - } + dshow_get_default_format(pin, config, devtype, &type); + if (!type) + // this pin does not expose any formats of the expected type + goto end; if (type) { // interrogate default format, so we know what to search for below @@ -1040,15 +1044,31 @@ next: CoTaskMemFree(type); type = NULL; } - // previously found a matching VIDEOINFOHEADER format and stored - // it for safe keeping. Searching further for a matching - // VIDEOINFOHEADER2 format yielded nothing. So set the pin's - // format based on the VIDEOINFOHEADER format. - // NB: this never applies to an audio format because - // previous_match_type always NULL in that case - if (pformat_set && !format_set && previous_match_type) { - if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) - format_set = 1; + + // set the pin's format, if wanted + if (pformat_set && !format_set) { + if (previous_match_type) { + // previously found a matching VIDEOINFOHEADER format and stored + // it for safe keeping. Searching further for a matching + // VIDEOINFOHEADER2 format yielded nothing. So set the pin's + // format based on the VIDEOINFOHEADER format. + // NB: this never applies to an audio format because + // previous_match_type always NULL in that case + if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) + format_set = 1; + } + else if (use_default) { + // default format returned by device apparently was not contained + // in the capabilities of any of the formats returned by the device + // (sic?). Fall back to directly setting the default format + dshow_get_default_format(pin, config, devtype, &type); + if (IAMStreamConfig_SetFormat(config, type) == S_OK) + format_set = 1; + if (type && type->pbFormat) + CoTaskMemFree(type->pbFormat); + CoTaskMemFree(type); + type = NULL; + } } end: From 3d53cefb49289e5e27b652e13623017b05ace452 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 1 Mar 2021 18:34:26 +0100 Subject: [PATCH 699/894] avcodec/raw: Reduce number of avpriv symbols libavcodec currently exports four avpriv symbols that deal with PixelFormatTags: avpriv_get_raw_pix_fmt_tags, avpriv_find_pix_fmt, avpriv_pix_fmt_bps_avi and avpriv_pix_fmt_bps_mov. The latter two are lists of PixelFormatTags, the former returns such a list and the second searches a list for a pixel format that matches a given fourcc; only one of the aforementioned three lists is ever searched. Yet for avpriv_pix_fmt_bps_avi, avpriv_pix_fmt_bps_mov and avpriv_find_pix_fmt the overhead of exporting these functions actually exceeds the size of said objects (at least for ELF; the following numbers are for x64 Ubuntu 20.10): The code size of avpriv_find_pix_fmt is small (GCC 10.2 37B, Clang 11 41B), yet exporting it adds a 20B string for the name alone to the exporting as well as to each importing library; there is more: Four bytes in the exporting libraries .gnu.hash; two bytes each for the exporting as well as each importing libraries .gnu.version; 24B in the exporting as well as each importing libraries .dynsym; 16B+24B for an entry in .plt as well as the accompanying relocation entry in .rela.plt for each importing library. The overhead for the lists is similar: The strings are 23B and the .plt+.rela.plt pair is replaced by 8B+24B for an entry in .got and a relocation entry in .rela.dyn. These lists have a size of 80 resp. 72 bytes. Yet for ff_raw_pix_fmt_tags, exporting it is advantageous compared to duplicating it into libavformat and potentially libavdevice. Therefore this commit replaces all library uses of the four symbols with a single function that is exported for shared builds. It has an enum parameter to choose the desired list besides the parameter for the fourcc. New lists can be supported with new enum values. Unfortunately, avpriv_get_raw_pix_fmt_tags could not be removed, as the fourcc2pixfmt tool uses the table of raw pix fmts. No other user of this function remains. Signed-off-by: Andreas Rheinhardt --- libavcodec/raw.c | 40 +++++++++++++++++++++++++++++++++++----- libavcodec/raw.h | 13 +++++++------ libavcodec/rawdec.c | 8 ++++---- libavcodec/utils.c | 11 ----------- libavdevice/dshow.c | 2 +- libavformat/avienc.c | 2 +- libavformat/demux.c | 2 +- libavformat/movenc.c | 2 +- 8 files changed, 50 insertions(+), 30 deletions(-) diff --git a/libavcodec/raw.c b/libavcodec/raw.c index 079d5c5d10..5efc1eb465 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c @@ -28,7 +28,7 @@ #include "raw.h" #include "libavutil/common.h" -const PixelFormatTag ff_raw_pix_fmt_tags[] = { +static const PixelFormatTag raw_pix_fmt_tags[] = { { AV_PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ { AV_PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') }, { AV_PIX_FMT_YUV420P, MKTAG('y', 'v', '1', '2') }, @@ -299,12 +299,12 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { const struct PixelFormatTag *avpriv_get_raw_pix_fmt_tags(void) { - return ff_raw_pix_fmt_tags; + return raw_pix_fmt_tags; } unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) { - const PixelFormatTag *tags = ff_raw_pix_fmt_tags; + const PixelFormatTag *tags = raw_pix_fmt_tags; while (tags->pix_fmt >= 0) { if (tags->pix_fmt == fmt) return tags->fourcc; @@ -313,7 +313,7 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) return 0; } -const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { +static const PixelFormatTag pix_fmt_bps_avi[] = { { AV_PIX_FMT_PAL8, 1 }, { AV_PIX_FMT_PAL8, 2 }, { AV_PIX_FMT_PAL8, 4 }, @@ -326,7 +326,7 @@ const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { { AV_PIX_FMT_NONE, 0 }, }; -const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { +static const PixelFormatTag pix_fmt_bps_mov[] = { { AV_PIX_FMT_PAL8, 1 }, { AV_PIX_FMT_PAL8, 2 }, { AV_PIX_FMT_PAL8, 4 }, @@ -337,3 +337,33 @@ const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { { AV_PIX_FMT_PAL8, 33 }, { AV_PIX_FMT_NONE, 0 }, }; + +static enum AVPixelFormat find_pix_fmt(const PixelFormatTag *tags, + unsigned int fourcc) +{ + while (tags->pix_fmt != AV_PIX_FMT_NONE) { + if (tags->fourcc == fourcc) + return tags->pix_fmt; + tags++; + } + return AV_PIX_FMT_NONE; +} + +enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, + unsigned fourcc) +{ + const PixelFormatTag *tags; + + switch (list) { + case PIX_FMT_LIST_RAW: + tags = raw_pix_fmt_tags; + break; + case PIX_FMT_LIST_AVI: + tags = pix_fmt_bps_avi; + break; + case PIX_FMT_LIST_MOV: + tags = pix_fmt_bps_mov; + break; + } + return find_pix_fmt(tags, fourcc); +} diff --git a/libavcodec/raw.h b/libavcodec/raw.h index 6a041690b1..9a4ddef8fc 100644 --- a/libavcodec/raw.h +++ b/libavcodec/raw.h @@ -28,20 +28,21 @@ #define AVCODEC_RAW_H #include "libavutil/pixfmt.h" -#include "internal.h" typedef struct PixelFormatTag { enum AVPixelFormat pix_fmt; unsigned int fourcc; } PixelFormatTag; -extern const PixelFormatTag ff_raw_pix_fmt_tags[]; // exposed through avpriv_get_raw_pix_fmt_tags() - const struct PixelFormatTag *avpriv_get_raw_pix_fmt_tags(void); -enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); +enum PixelFormatTagLists { + PIX_FMT_LIST_RAW, + PIX_FMT_LIST_AVI, + PIX_FMT_LIST_MOV, +}; -extern av_export_avcodec const PixelFormatTag avpriv_pix_fmt_bps_avi[]; -extern av_export_avcodec const PixelFormatTag avpriv_pix_fmt_bps_mov[]; +enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, + unsigned fourcc); #endif /* AVCODEC_RAW_H */ diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index b22e36e984..9724cce13f 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -76,15 +76,15 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) if ( avctx->codec_tag == MKTAG('r','a','w',' ') || avctx->codec_tag == MKTAG('N','O','1','6')) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV, avctx->bits_per_coded_sample); else if (avctx->codec_tag == MKTAG('W', 'R', 'A', 'W')) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, avctx->bits_per_coded_sample); else if (avctx->codec_tag && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) - avctx->pix_fmt = avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, avctx->codec_tag); + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, avctx->codec_tag); else if (avctx->pix_fmt == AV_PIX_FMT_NONE && avctx->bits_per_coded_sample) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, avctx->bits_per_coded_sample); desc = av_pix_fmt_desc_get(avctx->pix_fmt); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a91a54b0dc..4d236ff1cd 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -436,17 +436,6 @@ void ff_color_frame(AVFrame *frame, const int c[4]) } } -enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, - unsigned int fourcc) -{ - while (tags->pix_fmt >= 0) { - if (tags->fourcc == fourcc) - return tags->pix_fmt; - tags++; - } - return AV_PIX_FMT_NONE; -} - int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){ return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); } diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index a435ae1807..7e04880b38 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -76,7 +76,7 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) return AV_PIX_FMT_0RGB32; } } - return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others + return avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, biCompression); // all others } static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info) diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 3fbde0be1e..be2493ce55 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -448,7 +448,7 @@ static int avi_write_header(AVFormatContext *s) par->bits_per_coded_sample = 16; avist->pal_offset = avio_tell(pb) + 40; ff_put_bmp_header(pb, par, 0, 0, avi->flipped_raw_rgb); - pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, par->bits_per_coded_sample); if ( !par->codec_tag && par->codec_id == AV_CODEC_ID_RAWVIDEO diff --git a/libavformat/demux.c b/libavformat/demux.c index 3f35b3860e..4770e5517f 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2790,7 +2790,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (avctx->codec_id == AV_CODEC_ID_RAWVIDEO && !avctx->codec_tag && !avctx->bits_per_coded_sample) { uint32_t tag= avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt); - if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == avctx->pix_fmt) + if (avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, tag) == avctx->pix_fmt) avctx->codec_tag= tag; } diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 24965c89c2..bc6abcfcaa 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1637,7 +1637,7 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) } } - pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV, track->par->bits_per_coded_sample); if (tag == MKTAG('r','a','w',' ') && track->par->format != pix_fmt && From d7a75d21635eab4f4a1efea22945933059c2e36f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Feb 2021 18:25:13 +0100 Subject: [PATCH 700/894] avcodec/ac3tab: Unavpriv ac3_channel_layout_tab It is small (16 B) and therefore the overhead of exporting it more than outweighs the size savings from not having duplicated symbols: When the symbol is no longer avpriv, one saves twice the size of the string containing the symbols name (2x30 byte), two entries in .dynsym (24 bytes each on x64), one entry in the importing libraries .got and .rela.dyn (8 + 24 bytes on x64) and two entries for the symbol version (2 bytes each) and one hash value in the exporting library (4 bytes). (The exact numbers are of course different for other platforms (e.g. when using dlls), but given that the strings saved alone more than outweigh the array size it can be presumed that this is beneficial for all platforms.) Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 12 +++++--- libavcodec/ac3_channel_layout_tab.c | 22 +++++++++++++++ libavcodec/ac3_channel_layout_tab.h | 41 ++++++++++++++++++++++++++++ libavcodec/ac3_parser.c | 2 +- libavcodec/ac3dec.c | 4 +-- libavcodec/ac3enc.h | 1 + libavcodec/ac3tab.c | 14 ---------- libavcodec/ac3tab.h | 4 +-- libavcodec/eac3_data.c | 2 ++ libavformat/Makefile | 2 ++ libavformat/ac3_channel_layout_tab.c | 22 +++++++++++++++ libavformat/hls_sample_encryption.c | 4 ++- libavformat/mov.c | 4 +-- 13 files changed, 107 insertions(+), 27 deletions(-) create mode 100644 libavcodec/ac3_channel_layout_tab.c create mode 100644 libavcodec/ac3_channel_layout_tab.h create mode 100644 libavformat/ac3_channel_layout_tab.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e048a1c377..68a9075911 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -175,8 +175,10 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ psymodel.o mpeg4audio.o kbdwin.o OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o -OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o -OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o +OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o \ + kbdwin.o ac3tab.o ac3_channel_layout_tab.o +OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o \ + kbdwin.o ac3tab.o ac3_channel_layout_tab.o OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \ ac3.o kbdwin.o OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o kbdwin.o @@ -992,7 +994,6 @@ OBJS-$(CONFIG_FITS_DEMUXER) += fits.o OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o @@ -1001,6 +1002,8 @@ OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o @@ -1087,7 +1090,8 @@ OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ mpeg4audio.o -OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o +OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ + ac3_channel_layout_tab.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o diff --git a/libavcodec/ac3_channel_layout_tab.c b/libavcodec/ac3_channel_layout_tab.c new file mode 100644 index 0000000000..4fed46b6e7 --- /dev/null +++ b/libavcodec/ac3_channel_layout_tab.c @@ -0,0 +1,22 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ac3_channel_layout_tab.h" diff --git a/libavcodec/ac3_channel_layout_tab.h b/libavcodec/ac3_channel_layout_tab.h new file mode 100644 index 0000000000..46fa9ecdfe --- /dev/null +++ b/libavcodec/ac3_channel_layout_tab.h @@ -0,0 +1,41 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AC3_CHANNEL_LAYOUT_TAB_H +#define AVCODEC_AC3_CHANNEL_LAYOUT_TAB_H + +#include +#include "libavutil/channel_layout.h" + +/** + * Map audio coding mode (acmod) to channel layout mask. + */ +const uint16_t ff_ac3_channel_layout_tab[8] = { + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_5POINT0 +}; +#endif diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 9ed6ede5c3..f3c7d27d59 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -141,7 +141,7 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) (hdr->num_blocks * 256); hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; } - hdr->channel_layout = avpriv_ac3_channel_layout_tab[hdr->channel_mode]; + hdr->channel_layout = ff_ac3_channel_layout_tab[hdr->channel_mode]; if (hdr->lfe_on) hdr->channel_layout |= AV_CH_LOW_FREQUENCY; diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index c7deb56e1c..ae00373dcb 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1616,7 +1616,7 @@ dependent_frame: return AVERROR_INVALIDDATA; } avctx->channels = s->out_channels; - avctx->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; + avctx->channel_layout = ff_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; if (s->output_mode & AC3_OUTPUT_LFEON) avctx->channel_layout |= AV_CH_LOW_FREQUENCY; @@ -1700,7 +1700,7 @@ skip: extended_channel_map[ch] = ch; if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { - uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; + uint64_t ich_layout = ff_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on; uint64_t channel_layout; int extend = 0; diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index ec9ead8a4e..39a41fe0b0 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -35,6 +35,7 @@ #include "ac3dsp.h" #include "avcodec.h" #include "fft.h" +#include "internal.h" #include "mathops.h" #include "me_cmp.h" #include "put_bits.h" diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c index 5c5ea7e27e..766e293a1d 100644 --- a/libavcodec/ac3tab.c +++ b/libavcodec/ac3tab.c @@ -82,20 +82,6 @@ const uint8_t ff_ac3_channels_tab[8] = { 2, 1, 2, 3, 3, 4, 4, 5 }; -/** - * Map audio coding mode (acmod) to channel layout mask. - */ -const uint16_t avpriv_ac3_channel_layout_tab[8] = { - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_2_1, - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_2_2, - AV_CH_LAYOUT_5POINT0 -}; - /** * Table to remap channels from AC-3 order to SMPTE order. * [channel_mode][lfe][ch] diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h index ea8e3340c7..bc470204fe 100644 --- a/libavcodec/ac3tab.h +++ b/libavcodec/ac3tab.h @@ -24,13 +24,11 @@ #include -#include "libavutil/internal.h" #include "ac3.h" -#include "internal.h" extern const uint16_t ff_ac3_frame_size_tab[38][3]; extern const uint8_t ff_ac3_channels_tab[8]; -extern av_export_avcodec const uint16_t avpriv_ac3_channel_layout_tab[8]; +extern const uint16_t ff_ac3_channel_layout_tab[8]; extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; extern const int ff_ac3_sample_rate_tab[]; extern const uint16_t ff_ac3_bitrate_tab[19]; diff --git a/libavcodec/eac3_data.c b/libavcodec/eac3_data.c index b159e1682f..2ef0e2053c 100644 --- a/libavcodec/eac3_data.c +++ b/libavcodec/eac3_data.c @@ -24,6 +24,8 @@ * Tables taken directly from the E-AC-3 spec. */ +#include + #include "eac3_data.h" #include "ac3.h" diff --git a/libavformat/Makefile b/libavformat/Makefile index 37281d5ca8..df95c34046 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -681,6 +681,8 @@ OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o diff --git a/libavformat/ac3_channel_layout_tab.c b/libavformat/ac3_channel_layout_tab.c new file mode 100644 index 0000000000..cba198ccc5 --- /dev/null +++ b/libavformat/ac3_channel_layout_tab.c @@ -0,0 +1,22 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/ac3_channel_layout_tab.h" diff --git a/libavformat/hls_sample_encryption.c b/libavformat/hls_sample_encryption.c index 38795c7fb0..3dbaff717e 100644 --- a/libavformat/hls_sample_encryption.c +++ b/libavformat/hls_sample_encryption.c @@ -26,6 +26,8 @@ * https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption */ +#include "libavutil/channel_layout.h" + #include "hls_sample_encryption.h" #include "libavcodec/adts_header.h" @@ -129,7 +131,7 @@ int ff_hls_senc_parse_audio_setup_info(AVStream *st, HLSAudioSetupInfo *info) st->codecpar->sample_rate = eac3_sample_rate_tab[fscod]; - st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; diff --git a/libavformat/mov.c b/libavformat/mov.c index ad5ab6b491..e401cd39b5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -813,7 +813,7 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) acmod = (ac3info >> 11) & 0x7; lfeon = (ac3info >> 10) & 0x1; st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon; - st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; *ast = bsmod; @@ -846,7 +846,7 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) bsmod = (eac3info >> 12) & 0x1f; acmod = (eac3info >> 9) & 0x7; lfeon = (eac3info >> 8) & 0x1; - st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); From 3afb41655e2afa8f4284f7fc19153cccf62afaa3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Feb 2021 21:16:18 +0100 Subject: [PATCH 701/894] avcodec/dca: Unavpriv dca_sample_rates Said table is 64 bytes long and exported so that it can be used both in libavcodec and libavformat. This commit stops doing so and instead duplicates it for shared builds, because the overhead of exporting the symbol is bigger than 64 bytes. It consists of the length of the name of the symbol (2x24 bytes), two entries in .dynsym (2x24 bytes), two entries for symbol version (2x2 bytes), one hash value in the exporting library (4 bytes) in addition to one entry in the importing library's .got and .rela.dyn (8 + 24 bytes). (The above numbers are for a Linux/GNU/Elf system; the numbers for other platforms may be different.) Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 8 +++++--- libavcodec/dca.c | 7 +------ libavcodec/dca.h | 4 +--- libavcodec/dca_core.c | 2 +- libavcodec/dca_parser.c | 2 +- libavcodec/dca_sample_rate_tab.c | 25 +++++++++++++++++++++++ libavcodec/dca_sample_rate_tab.h | 33 +++++++++++++++++++++++++++++++ libavformat/Makefile | 1 + libavformat/dca_sample_rate_tab.c | 25 +++++++++++++++++++++++ libavformat/spdifenc.c | 2 +- 10 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 libavcodec/dca_sample_rate_tab.c create mode 100644 libavcodec/dca_sample_rate_tab.h create mode 100644 libavformat/dca_sample_rate_tab.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 68a9075911..2500c3ee55 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -276,7 +276,8 @@ OBJS-$(CONFIG_CSCD_DECODER) += cscd.o OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadata.o dcahuff.o \ dca_core.o dca_exss.o dca_xll.o dca_lbr.o \ - dcadsp.o dcadct.o synth_filter.o + dcadsp.o dcadct.o dca_sample_rate_tab.o \ + synth_filter.o OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dcadata.o dcahuff.o \ dcaadpcm.o OBJS-$(CONFIG_DDS_DECODER) += dds.o @@ -997,7 +998,6 @@ OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o @@ -1006,6 +1006,7 @@ STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies OBJS-$(CONFIG_ELBG_FILTER) += elbg.o @@ -1101,7 +1102,8 @@ OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o OBJS-$(CONFIG_CRI_PARSER) += cri_parser.o -OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca_exss.o dca.o +OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca_exss.o dca.o \ + dca_sample_rate_tab.o OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o OBJS-$(CONFIG_DNXHD_PARSER) += dnxhd_parser.o dnxhddata.o OBJS-$(CONFIG_DOLBY_E_PARSER) += dolby_e_parser.o dolby_e_parse.o diff --git a/libavcodec/dca.c b/libavcodec/dca.c index b2152524a5..fb359b2ff3 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -33,11 +33,6 @@ #include "get_bits.h" #include "put_bits.h" -const uint32_t avpriv_dca_sample_rates[16] = { - 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, - 12000, 24000, 48000, 96000, 192000 -}; - const uint32_t ff_dca_sampling_freqs[16] = { 8000, 16000, 32000, 64000, 128000, 22050, 44100, 88200, 176400, 352800, 12000, 24000, 48000, 96000, 192000, 384000, @@ -112,7 +107,7 @@ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb) return DCA_PARSE_ERROR_AMODE; h->sr_code = get_bits(gb, 4); - if (!avpriv_dca_sample_rates[h->sr_code]) + if (!ff_dca_sample_rates[h->sr_code]) return DCA_PARSE_ERROR_SAMPLE_RATE; h->br_code = get_bits(gb, 5); diff --git a/libavcodec/dca.h b/libavcodec/dca.h index e96c589c02..6be975fdfa 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -32,7 +32,6 @@ #include "libavutil/intreadwrite.h" #include "get_bits.h" -#include "internal.h" #define DCA_CORE_FRAME_HEADER_SIZE 18 @@ -195,8 +194,7 @@ enum DCADownMixType { DCA_DMIX_TYPE_COUNT }; -extern av_export_avcodec const uint32_t avpriv_dca_sample_rates[16]; - +extern const uint32_t ff_dca_sample_rates[16]; extern const uint32_t ff_dca_sampling_freqs[16]; extern const uint8_t ff_dca_freq_ranges[16]; extern const uint8_t ff_dca_bits_per_sample[8]; diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c index f0a3c18d62..758e3447a6 100644 --- a/libavcodec/dca_core.c +++ b/libavcodec/dca_core.c @@ -129,7 +129,7 @@ static int parse_frame_header(DCACoreDecoder *s) s->npcmblocks = h.npcmblocks; s->frame_size = h.frame_size; s->audio_mode = h.audio_mode; - s->sample_rate = avpriv_dca_sample_rates[h.sr_code]; + s->sample_rate = ff_dca_sample_rates[h.sr_code]; s->bit_rate = ff_dca_bit_rates[h.br_code]; s->drc_present = h.drc_present; s->ts_present = h.ts_present; diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c index 8b5c354312..3148397b7d 100644 --- a/libavcodec/dca_parser.c +++ b/libavcodec/dca_parser.c @@ -267,7 +267,7 @@ static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf, return AVERROR_INVALIDDATA; *duration = h.npcmblocks * DCA_PCMBLOCK_SAMPLES; - *sample_rate = avpriv_dca_sample_rates[h.sr_code]; + *sample_rate = ff_dca_sample_rates[h.sr_code]; if (*profile != FF_PROFILE_UNKNOWN) return 0; diff --git a/libavcodec/dca_sample_rate_tab.c b/libavcodec/dca_sample_rate_tab.c new file mode 100644 index 0000000000..16ee04b1d2 --- /dev/null +++ b/libavcodec/dca_sample_rate_tab.c @@ -0,0 +1,25 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dca_sample_rate_tab.h" diff --git a/libavcodec/dca_sample_rate_tab.h b/libavcodec/dca_sample_rate_tab.h new file mode 100644 index 0000000000..93d9a13663 --- /dev/null +++ b/libavcodec/dca_sample_rate_tab.h @@ -0,0 +1,33 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larssonb + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DCA_SAMPLE_RATE_TAB_H +#define AVCODEC_DCA_SAMPLE_RATE_TAB_H +#include + +const uint32_t ff_dca_sample_rates[16] = { + 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, + 12000, 24000, 48000, 96000, 192000 +}; +#endif diff --git a/libavformat/Makefile b/libavformat/Makefile index df95c34046..82e7fd3dc7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -685,6 +685,7 @@ SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavdevice dependencies OBJS-$(CONFIG_IEC61883_INDEV) += dv.o diff --git a/libavformat/dca_sample_rate_tab.c b/libavformat/dca_sample_rate_tab.c new file mode 100644 index 0000000000..ed2380b0cd --- /dev/null +++ b/libavformat/dca_sample_rate_tab.c @@ -0,0 +1,25 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/dca_sample_rate_tab.h" diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index e8f54bff4b..3be89328df 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -263,7 +263,7 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt) case DCA_SYNCWORD_CORE_BE: blocks = (AV_RB16(pkt->data + 4) >> 2) & 0x7f; core_size = ((AV_RB24(pkt->data + 5) >> 4) & 0x3fff) + 1; - sample_rate = avpriv_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; + sample_rate = ff_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; break; case DCA_SYNCWORD_CORE_LE: blocks = (AV_RL16(pkt->data + 4) >> 2) & 0x7f; From 1d333c154718f3851b3af2d86663451d353e3685 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 10 Feb 2021 01:19:44 +0100 Subject: [PATCH 702/894] avcodec/jpegtables: Unavpriv MJPEG-tables There are seven MJPEG-tables, five small (1x12, 4x17) and two not small (2x162). These are all avpriv, despite this not being worthwhile due to the overhead of exporting a symbol: The total overhead for each symbol consists of two entries in .dynsym (24B each), one entry in the importing library's .rela.dyn (24B) and one in .got (8B) as well as 2x2B for symbol versions and 4B for symbol hashes in the exporting library; in addition to that, the name of the symbol is included in both exporting and importing libraries, using 2x210 bytes in this case. (The above numbers are for a x64 Elf/Linux/GNU system. Other platforms will give different numbers.) Signed-off-by: Andreas Rheinhardt --- configure | 3 +- libavcodec/Makefile | 3 +- libavcodec/g2meet.c | 16 +++--- libavcodec/jpegtables.c | 66 +---------------------- libavcodec/jpegtables.h | 16 +++--- libavcodec/jpegtabs.h | 92 +++++++++++++++++++++++++++++++++ libavcodec/ljpegenc.c | 8 +-- libavcodec/mjpeg2jpeg_bsf.c | 12 ++--- libavcodec/mjpegdec.c | 24 ++++----- libavcodec/mjpegenc.c | 16 +++--- libavcodec/mjpegenc_common.c | 16 +++--- libavcodec/mss4.c | 8 +-- libavcodec/vaapi_encode_mjpeg.c | 16 +++--- libavformat/Makefile | 3 +- libavformat/jpegtables.c | 24 +++++++++ libavformat/rtpdec_jpeg.c | 16 +++--- libavformat/rtpenc_jpeg.c | 16 +++--- 17 files changed, 203 insertions(+), 152 deletions(-) create mode 100644 libavcodec/jpegtabs.h create mode 100644 libavformat/jpegtables.c diff --git a/configure b/configure index 50aa0d596d..f04288cf8d 100755 --- a/configure +++ b/configure @@ -3451,9 +3451,8 @@ ogv_muxer_select="ogg_muxer" opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtp_muxer_select="jpegtables" rtp_mpegts_muxer_select="mpegts_muxer rtp_muxer" -rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" +rtpdec_select="asf_demuxer mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" rtsp_demuxer_select="http_protocol rtpdec" rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain" sap_demuxer_select="sdp_demuxer" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2500c3ee55..4afc290710 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1005,7 +1005,8 @@ OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o -STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index c9e8d11ab8..4c53838af5 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -164,20 +164,20 @@ static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c) { int ret; - ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 0, avctx); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 0, avctx); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 1, avctx); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 1, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 1, avctx); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 1, avctx); if (ret) return ret; diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index ef3f8dee20..e453fcf90d 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -30,8 +30,7 @@ * MJPEG encoder and decoder. */ -#include "jpegtables.h" - +#include "jpegtabs.h" #if 0 /* These are the sample quantization tables given in JPEG spec section K.1. @@ -59,66 +58,3 @@ static const unsigned char std_chrominance_quant_tbl[64] = { 99, 99, 99, 99, 99, 99, 99, 99 }; #endif - -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ -const uint8_t avpriv_mjpeg_bits_dc_luminance[17] = -{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; -const uint8_t avpriv_mjpeg_val_dc[12] = -{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - -const uint8_t avpriv_mjpeg_bits_dc_chrominance[17] = -{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; - -const uint8_t avpriv_mjpeg_bits_ac_luminance[17] = -{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; -const uint8_t avpriv_mjpeg_val_ac_luminance[] = -{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - -const uint8_t avpriv_mjpeg_bits_ac_chrominance[17] = -{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; - -const uint8_t avpriv_mjpeg_val_ac_chrominance[] = -{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; diff --git a/libavcodec/jpegtables.h b/libavcodec/jpegtables.h index 0907280445..49b5ecdeb0 100644 --- a/libavcodec/jpegtables.h +++ b/libavcodec/jpegtables.h @@ -23,17 +23,15 @@ #include -#include "internal.h" +extern const uint8_t ff_mjpeg_bits_dc_luminance[]; +extern const uint8_t ff_mjpeg_val_dc[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_dc[]; +extern const uint8_t ff_mjpeg_bits_dc_chrominance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; +extern const uint8_t ff_mjpeg_bits_ac_luminance[]; +extern const uint8_t ff_mjpeg_val_ac_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_luminance[]; - -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_chrominance[]; +extern const uint8_t ff_mjpeg_bits_ac_chrominance[]; +extern const uint8_t ff_mjpeg_val_ac_chrominance[]; #endif /* AVCODEC_JPEGTABLES_H */ diff --git a/libavcodec/jpegtabs.h b/libavcodec/jpegtabs.h new file mode 100644 index 0000000000..7106f66df0 --- /dev/null +++ b/libavcodec/jpegtabs.h @@ -0,0 +1,92 @@ +/* + * MJPEG tables + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_JPEGTABS_H +#define AVCODEC_JPEGTABS_H + +#include +#include "jpegtables.h" + +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +const uint8_t ff_mjpeg_bits_dc_luminance[17] = +{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +const uint8_t ff_mjpeg_val_dc[12] = +{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + +const uint8_t ff_mjpeg_bits_dc_chrominance[17] = +{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + +const uint8_t ff_mjpeg_bits_ac_luminance[17] = +{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; +const uint8_t ff_mjpeg_val_ac_luminance[] = +{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +const uint8_t ff_mjpeg_bits_ac_chrominance[17] = +{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + +const uint8_t ff_mjpeg_val_ac_chrominance[] = +{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; +#endif diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index 968ba1fb60..ecdedeb6a3 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -293,12 +293,12 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) ff_mjpeg_build_huffman_codes(s->huff_size_dc_luminance, s->huff_code_dc_luminance, - avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(s->huff_size_dc_chrominance, s->huff_code_dc_chrominance, - avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); return 0; } diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c index b30f391bf9..2a972a7c37 100644 --- a/libavcodec/mjpeg2jpeg_bsf.c +++ b/libavcodec/mjpeg2jpeg_bsf.c @@ -65,15 +65,15 @@ static uint8_t *append(uint8_t *buf, const uint8_t *src, int size) static uint8_t *append_dht_segment(uint8_t *buf) { buf = append(buf, dht_segment_head, sizeof(dht_segment_head)); - buf = append(buf, avpriv_mjpeg_bits_dc_luminance + 1, 16); + buf = append(buf, ff_mjpeg_bits_dc_luminance + 1, 16); buf = append(buf, dht_segment_frag, sizeof(dht_segment_frag)); - buf = append(buf, avpriv_mjpeg_val_dc, 12); + buf = append(buf, ff_mjpeg_val_dc, 12); *(buf++) = 0x10; - buf = append(buf, avpriv_mjpeg_bits_ac_luminance + 1, 16); - buf = append(buf, avpriv_mjpeg_val_ac_luminance, 162); + buf = append(buf, ff_mjpeg_bits_ac_luminance + 1, 16); + buf = append(buf, ff_mjpeg_val_ac_luminance, 162); *(buf++) = 0x11; - buf = append(buf, avpriv_mjpeg_bits_ac_chrominance + 1, 16); - buf = append(buf, avpriv_mjpeg_val_ac_chrominance, 162); + buf = append(buf, ff_mjpeg_bits_ac_chrominance + 1, 16); + buf = append(buf, ff_mjpeg_val_ac_chrominance, 162); return buf; } diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0dbbc14bae..a735d2337d 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -61,18 +61,18 @@ static int init_default_huffman_tables(MJpegDecodeContext *s) const uint8_t *values; int length; } ht[] = { - { 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 12 }, - { 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 12 }, - { 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 162 }, - { 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 162 }, - { 2, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 162 }, - { 2, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 162 }, + { 0, 0, ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 12 }, + { 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 12 }, + { 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 162 }, + { 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 162 }, + { 2, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 162 }, + { 2, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 162 }, }; int i, ret; diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 0ade66bc5f..30cbbddb59 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -288,20 +288,20 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) // they are needed at least right now for some processes like trellis. ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, m->huff_code_dc_luminance, - avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, m->huff_code_dc_chrominance, - avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, m->huff_code_ac_luminance, - avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); + ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, m->huff_code_ac_chrominance, - avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index c1b842d547..368e87128c 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -121,15 +121,15 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, size += put_huffman_table(p, 1, 1, s->mjpeg_ctx->bits_ac_chrominance, s->mjpeg_ctx->val_ac_chrominance); } else { - size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + size += put_huffman_table(p, 0, 0, ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + size += put_huffman_table(p, 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); - size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + size += put_huffman_table(p, 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + size += put_huffman_table(p, 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); } AV_WB16(ptr, size); } diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c index 6c44c76c50..216df2852d 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -124,10 +124,10 @@ static av_cold void mss4_init_vlcs(void) for (unsigned i = 0, offset = 0; i < 2; i++) { mss4_init_vlc(&dc_vlc[i], &offset, mss4_dc_vlc_lens[i], NULL); mss4_init_vlc(&ac_vlc[i], &offset, - i ? avpriv_mjpeg_bits_ac_chrominance + 1 - : avpriv_mjpeg_bits_ac_luminance + 1, - i ? avpriv_mjpeg_val_ac_chrominance - : avpriv_mjpeg_val_ac_luminance); + i ? ff_mjpeg_bits_ac_chrominance + 1 + : ff_mjpeg_bits_ac_luminance + 1, + i ? ff_mjpeg_val_ac_chrominance + : ff_mjpeg_val_ac_luminance); mss4_init_vlc(&vec_entry_vlc[i], &offset, mss4_vec_entry_vlc_lens[i], mss4_vec_entry_vlc_syms[i]); } diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index d35f416ad7..6206b23e5f 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -327,20 +327,20 @@ static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx, switch (t) { case 0: - lengths = avpriv_mjpeg_bits_dc_luminance + 1; - values = avpriv_mjpeg_val_dc; + lengths = ff_mjpeg_bits_dc_luminance + 1; + values = ff_mjpeg_val_dc; break; case 1: - lengths = avpriv_mjpeg_bits_ac_luminance + 1; - values = avpriv_mjpeg_val_ac_luminance; + lengths = ff_mjpeg_bits_ac_luminance + 1; + values = ff_mjpeg_val_ac_luminance; break; case 2: - lengths = avpriv_mjpeg_bits_dc_chrominance + 1; - values = avpriv_mjpeg_val_dc; + lengths = ff_mjpeg_bits_dc_chrominance + 1; + values = ff_mjpeg_val_dc; break; case 3: - lengths = avpriv_mjpeg_bits_ac_chrominance + 1; - values = avpriv_mjpeg_val_ac_chrominance; + lengths = ff_mjpeg_bits_ac_chrominance + 1; + values = ff_mjpeg_val_ac_chrominance; break; } diff --git a/libavformat/Makefile b/libavformat/Makefile index 82e7fd3dc7..f5d6b8fecf 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -684,7 +684,8 @@ SHLIBOBJS += log2_tab.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o -SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavdevice dependencies diff --git a/libavformat/jpegtables.c b/libavformat/jpegtables.c new file mode 100644 index 0000000000..57eae9f9a6 --- /dev/null +++ b/libavformat/jpegtables.c @@ -0,0 +1,24 @@ +/* + * MJPEG tables + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/jpegtabs.h" diff --git a/libavformat/rtpdec_jpeg.c b/libavformat/rtpdec_jpeg.c index b32d074136..81036247c1 100644 --- a/libavformat/rtpdec_jpeg.c +++ b/libavformat/rtpdec_jpeg.c @@ -144,14 +144,14 @@ static int jpeg_create_header(uint8_t *buf, int size, uint32_t type, uint32_t w, bytestream2_put_be16(&pbc, 0); dht_size = 2; - dht_size += jpeg_create_huffman_table(&pbc, 0, 0,avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - dht_size += jpeg_create_huffman_table(&pbc, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); - dht_size += jpeg_create_huffman_table(&pbc, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - dht_size += jpeg_create_huffman_table(&pbc, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + dht_size += jpeg_create_huffman_table(&pbc, 0, 0,ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + dht_size += jpeg_create_huffman_table(&pbc, 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); + dht_size += jpeg_create_huffman_table(&pbc, 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + dht_size += jpeg_create_huffman_table(&pbc, 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); AV_WB16(dht_size_ptr, dht_size); /* SOF0 */ diff --git a/libavformat/rtpenc_jpeg.c b/libavformat/rtpenc_jpeg.c index 38eb2e68eb..91116832da 100644 --- a/libavformat/rtpenc_jpeg.c +++ b/libavformat/rtpenc_jpeg.c @@ -101,8 +101,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) switch (buf[i + 1]) { case 0x00: if ( dht_size >= 29 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_luminance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_luminance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { default_huffman_tables |= 1; i += 29; dht_size -= 29; @@ -113,8 +113,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x01: if ( dht_size >= 29 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_chrominance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_chrominance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { default_huffman_tables |= 1 << 1; i += 29; dht_size -= 29; @@ -125,8 +125,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x10: if ( dht_size >= 179 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_luminance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_luminance, 162)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_luminance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_ac_luminance, 162)) { default_huffman_tables |= 1 << 2; i += 179; dht_size -= 179; @@ -137,8 +137,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x11: if ( dht_size >= 179 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_chrominance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_chrominance, 162)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_chrominance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_ac_chrominance, 162)) { default_huffman_tables |= 1 << 3; i += 179; dht_size -= 179; From d82c91ba2f889bc5e0ee7c976219f91e62dc9f8b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 14 Dec 2021 11:19:08 +0100 Subject: [PATCH 703/894] configure, avcodec/Makefile: Add new mpeg4audio CONFIG_EXTRA group This group is mainly for the users of *_mpeg4audio_get_config2(); it is not for those who only use avpriv_mpeg4audio_sample_rates. This is in preparation for splitting the latter into a file of its own; if there were no CONFIG_EXTRA group for *_mpeg4audio_get_config2() users, one would have to add a dependency to the new file for all these users on top of the existing dependency on mpeg4audio.o. Adding a new CONFIG_EXTRA group only takes effect after a reconfigure; so in order to force a reconfigure some unnecessary headers from libavdevice/alldevices.c have been removed. Signed-off-by: Andreas Rheinhardt --- configure | 23 +++++++++++++---------- libavcodec/Makefile | 23 +++++++++-------------- libavdevice/alldevices.c | 2 -- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/configure b/configure index f04288cf8d..729e9b5ac7 100755 --- a/configure +++ b/configure @@ -2476,6 +2476,7 @@ CONFIG_EXTRA=" mpegaudio mpegaudiodsp mpegaudioheader + mpeg4audio mpegvideo mpegvideoenc mss34dsp @@ -2719,6 +2720,7 @@ h264dsp_select="startcode" hevcparse_select="atsc_a53 golomb" frame_thread_encoder_deps="encoders threads" intrax8_select="blockdsp idctdsp" +iso_media_select="mpeg4audio" mdct_select="fft" mdct15_select="fft" me_cmp_select="fdctdsp idctdsp pixblockdsp" @@ -2731,8 +2733,8 @@ vc1dsp_select="h264chroma qpeldsp startcode" rdft_select="fft" # decoders / encoders -aac_decoder_select="adts_header mdct15 mdct sinewin" -aac_fixed_decoder_select="adts_header mdct" +aac_decoder_select="adts_header mdct15 mdct mpeg4audio sinewin" +aac_fixed_decoder_select="adts_header mdct mpeg4audio" aac_encoder_select="audio_frame_queue iirfilter lpc mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" @@ -2744,7 +2746,7 @@ adpcm_g722_decoder_select="g722dsp" adpcm_g722_encoder_select="g722dsp" aic_decoder_select="golomb idctdsp" alac_encoder_select="lpc" -als_decoder_select="bswapdsp" +als_decoder_select="bswapdsp mpeg4audio" amrnb_decoder_select="lsp" amrwb_decoder_select="lsp" amv_decoder_select="sp5x_decoder exif" @@ -2864,8 +2866,8 @@ mp3_decoder_select="mpegaudio" mp3adu_decoder_select="mpegaudio" mp3adufloat_decoder_select="mpegaudio" mp3float_decoder_select="mpegaudio" -mp3on4_decoder_select="mpegaudio" -mp3on4float_decoder_select="mpegaudio" +mp3on4_decoder_select="mpegaudio mpeg4audio" +mp3on4float_decoder_select="mpegaudio mpeg4audio" mpc7_decoder_select="bswapdsp mpegaudiodsp" mpc8_decoder_select="mpegaudiodsp" mpegvideo_decoder_select="mpegvideo" @@ -3242,7 +3244,7 @@ wmv3_crystalhd_decoder_select="crystalhd" av1_qsv_decoder_select="qsvdec" # parsers -aac_parser_select="adts_header" +aac_parser_select="adts_header mpeg4audio" av1_parser_select="cbs_av1" h264_parser_select="atsc_a53 golomb h264dsp h264parse" hevc_parser_select="hevcparse" @@ -3252,7 +3254,7 @@ mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" vc1_parser_select="vc1dsp" # bitstream_filters -aac_adtstoasc_bsf_select="adts_header" +aac_adtstoasc_bsf_select="adts_header mpeg4audio" av1_frame_merge_bsf_select="cbs_av1" av1_frame_split_bsf_select="cbs_av1" av1_metadata_bsf_select="cbs_av1" @@ -3387,6 +3389,7 @@ videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrame # demuxers / muxers ac3_demuxer_select="ac3_parser" act_demuxer_select="riffdec" +adts_muxer_select="mpeg4audio" aiff_muxer_select="iso_media" asf_demuxer_select="riffdec" asf_o_demuxer_select="riffdec" @@ -3422,11 +3425,11 @@ imf_demuxer_select="mxf_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" -latm_muxer_select="aac_adtstoasc_bsf" +latm_muxer_select="aac_adtstoasc_bsf mpeg4audio" matroska_audio_muxer_select="matroska_muxer" matroska_demuxer_select="riffdec" matroska_demuxer_suggest="bzlib lzo zlib" -matroska_muxer_select="riffenc vp9_superframe_bsf aac_adtstoasc_bsf" +matroska_muxer_select="mpeg4audio riffenc vp9_superframe_bsf aac_adtstoasc_bsf" mlp_demuxer_select="mlp_parser" mmf_muxer_select="riffenc" mov_demuxer_select="iso_media riffdec" @@ -3473,7 +3476,7 @@ w64_muxer_select="wav_muxer" wav_demuxer_select="riffdec" wav_muxer_select="riffenc" webm_chunk_muxer_select="webm_muxer" -webm_muxer_select="riffenc" +webm_muxer_select="mpeg4audio riffenc" webm_dash_manifest_demuxer_select="matroska_demuxer" wtv_demuxer_select="mpegts_demuxer riffdec" wtv_muxer_select="mpegts_muxer riffenc" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4afc290710..6b141d3706 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -124,6 +124,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.o +OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ mpegvideodata.o mpegpicture.o @@ -161,10 +162,10 @@ OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_common.o aacps_float.o \ - mpeg4audio.o kbdwin.o \ + kbdwin.o \ sbrdsp.o aacpsdsp_float.o cbrt_data.o OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_common.o aacps_fixed.o \ - mpeg4audio.o kbdwin.o \ + kbdwin.o \ sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacpsy.o aactab.o \ @@ -190,7 +191,7 @@ OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o alacdsp.o OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o OBJS-$(CONFIG_ALIAS_PIX_DECODER) += aliaspixdec.o OBJS-$(CONFIG_ALIAS_PIX_ENCODER) += aliaspixenc.o -OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o mpeg4audio.o +OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ celp_math.o acelp_filters.o \ acelp_vectors.o \ @@ -481,8 +482,8 @@ OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP3FLOAT_DECODER) += mpegaudiodec_float.o -OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o mpeg4audio.o -OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o +OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o +OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o @@ -988,18 +989,13 @@ OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o SHLIBOBJS += log2_tab.o reverse.o # General libavformat dependencies -OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_ISO_MEDIA) += mpegaudiodata.o -OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o -OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # libavformat dependencies for static builds STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o @@ -1090,8 +1086,7 @@ OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o # parsers OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o -OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ - mpeg4audio.o +OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ ac3_channel_layout_tab.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o @@ -1151,7 +1146,7 @@ OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o # bitstream filters -OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o +OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index fbbe187a51..22323a0a44 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -18,8 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" -#include "libavutil/thread.h" #include "libavformat/internal.h" #include "avdevice.h" From 49bf94536f059340eacd5430592e4216b29d0d20 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 10 Feb 2021 19:37:37 +0100 Subject: [PATCH 704/894] avcodec/mpeg4audio: Unavpriv and deduplicate mpeg4audio_sample_rates avpriv_mpeg4audio_sample_rates has a size of 64B and it is currently avpriv; a clone of it exists in aacenctab.h and from there it is inlined in aacenc.c (which also uses the avpriv version) and in the FLV muxer. This means that despite it being avpriv both libavformat as well as libavcodec have copies already. This situation is clearly suboptimal. Given the overhead of exporting symbols (for x64 Elf/Linux/GNU: 2x2B version, 2x24B .dynsym, 24B .rela.dyn, 8B .got, 4B hash + twice the size of the name (here 31B)) the object is unavprived, i.e. duplicated into libavformat when creating a shared build; but the duplicates in the AAC encoder and FLV muxer are removed. This involves splitting of the sample rate table into a file of its own; this allowed to break some spurious dependencies (e.g. both the AAC encoder as well as the Matroska demuxer actually don't need the mpeg4audio_get_config stuff). Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 14 +++++++------ libavcodec/aacenc.c | 4 ++-- libavcodec/aacenctab.h | 7 ------- libavcodec/adts_header.c | 4 ++-- libavcodec/mpeg4audio.c | 9 +------- libavcodec/mpeg4audio.h | 3 +-- libavcodec/mpeg4audio_sample_rates.c | 23 ++++++++++++++++++++ libavcodec/mpeg4audio_sample_rates.h | 30 +++++++++++++++++++++++++++ libavformat/Makefile | 5 ++++- libavformat/flvenc.c | 4 ++-- libavformat/matroskadec.c | 4 ++-- libavformat/mpeg4audio_sample_rates.c | 23 ++++++++++++++++++++ libavformat/sdp.c | 2 +- 13 files changed, 99 insertions(+), 33 deletions(-) create mode 100644 libavcodec/mpeg4audio_sample_rates.c create mode 100644 libavcodec/mpeg4audio_sample_rates.h create mode 100644 libavformat/mpeg4audio_sample_rates.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6b141d3706..63b4952eaf 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -60,7 +60,7 @@ OBJS = ac3_parser.o \ # subsystems OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o -OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o +OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_AMF) += amfenc.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o OBJS-$(CONFIG_ATSC_A53) += atsc_a53.o @@ -124,7 +124,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.o -OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o +OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ mpegvideodata.o mpegpicture.o @@ -173,7 +173,8 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacenc_tns.o \ aacenc_ltp.o \ aacenc_pred.o \ - psymodel.o mpeg4audio.o kbdwin.o + psymodel.o kbdwin.o \ + mpeg4audio_sample_rates.o OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o \ @@ -992,17 +993,18 @@ SHLIBOBJS += log2_tab.o reverse.o OBJS-$(CONFIG_ISO_MEDIA) += mpegaudiodata.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o -OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o -STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o \ + mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index e462566078..a1004c3e98 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -998,7 +998,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Samplerate */ for (i = 0; i < 16; i++) - if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i]) + if (avctx->sample_rate == ff_mpeg4audio_sample_rates[i]) break; s->samplerate_index = i; ERROR_IF(s->samplerate_index == 16 || @@ -1143,7 +1143,7 @@ const AVCodec ff_aac_encoder = { .encode2 = aac_encode_frame, .close = aac_encode_end, .defaults = aac_encode_defaults, - .supported_samplerates = mpeg4audio_sample_rates, + .supported_samplerates = ff_mpeg4audio_sample_rates, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h index f54dd16bed..33cb7ae95b 100644 --- a/libavcodec/aacenctab.h +++ b/libavcodec/aacenctab.h @@ -81,13 +81,6 @@ static const uint8_t aac_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = { { 2, 0, 1, 6, 7, 4, 5, 3 }, }; -/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build - * failures */ -static const int mpeg4audio_sample_rates[16] = { - 96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000, 7350 -}; - /** bits needed to code codebook run value for long windows */ static const uint8_t run_value_bits_long[64] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, diff --git a/libavcodec/adts_header.c b/libavcodec/adts_header.c index e4454529c4..ff4efafbf7 100644 --- a/libavcodec/adts_header.c +++ b/libavcodec/adts_header.c @@ -40,7 +40,7 @@ int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) crc_abs = get_bits1(gbc); /* protection_absent */ aot = get_bits(gbc, 2); /* profile_objecttype */ sr = get_bits(gbc, 4); /* sample_frequency_index */ - if (!avpriv_mpeg4audio_sample_rates[sr]) + if (!ff_mpeg4audio_sample_rates[sr]) return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; skip_bits1(gbc); /* private_bit */ ch = get_bits(gbc, 3); /* channel_configuration */ @@ -63,7 +63,7 @@ int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) hdr->crc_absent = crc_abs; hdr->num_aac_frames = rdb + 1; hdr->sampling_index = sr; - hdr->sample_rate = avpriv_mpeg4audio_sample_rates[sr]; + hdr->sample_rate = ff_mpeg4audio_sample_rates[sr]; hdr->samples = (rdb + 1) * 1024; hdr->bit_rate = size * 8 * hdr->sample_rate / hdr->samples; hdr->frame_length = size; diff --git a/libavcodec/mpeg4audio.c b/libavcodec/mpeg4audio.c index be50de9052..ed72a80f6d 100644 --- a/libavcodec/mpeg4audio.c +++ b/libavcodec/mpeg4audio.c @@ -57,13 +57,6 @@ static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c, void *logctx return 0; } -/* XXX: make sure to update the copies in the different encoders if you change - * this table */ -const int avpriv_mpeg4audio_sample_rates[16] = { - 96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000, 7350 -}; - const uint8_t ff_mpeg4audio_channels[14] = { 0, 1, // mono (1/0) @@ -93,7 +86,7 @@ static inline int get_sample_rate(GetBitContext *gb, int *index) { *index = get_bits(gb, 4); return *index == 0x0f ? get_bits(gb, 24) : - avpriv_mpeg4audio_sample_rates[*index]; + ff_mpeg4audio_sample_rates[*index]; } int ff_mpeg4audio_get_config_gb(MPEG4AudioConfig *c, GetBitContext *gb, diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h index 3187df68d2..c486a3ddef 100644 --- a/libavcodec/mpeg4audio.h +++ b/libavcodec/mpeg4audio.h @@ -27,7 +27,6 @@ #include "libavutil/attributes.h" #include "get_bits.h" -#include "internal.h" #include "put_bits.h" typedef struct MPEG4AudioConfig { @@ -45,7 +44,7 @@ typedef struct MPEG4AudioConfig { int frame_length_short; } MPEG4AudioConfig; -extern av_export_avcodec const int avpriv_mpeg4audio_sample_rates[16]; +extern const int ff_mpeg4audio_sample_rates[16]; extern const uint8_t ff_mpeg4audio_channels[14]; /** diff --git a/libavcodec/mpeg4audio_sample_rates.c b/libavcodec/mpeg4audio_sample_rates.c new file mode 100644 index 0000000000..b5ceb59c6e --- /dev/null +++ b/libavcodec/mpeg4audio_sample_rates.c @@ -0,0 +1,23 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mpeg4audio_sample_rates.h" diff --git a/libavcodec/mpeg4audio_sample_rates.h b/libavcodec/mpeg4audio_sample_rates.h new file mode 100644 index 0000000000..0b8caa6d76 --- /dev/null +++ b/libavcodec/mpeg4audio_sample_rates.h @@ -0,0 +1,30 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEG4AUDIO_SAMPLE_RATES_H +#define AVCODEC_MPEG4AUDIO_SAMPLE_RATES_H + +const int ff_mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; +#endif diff --git a/libavformat/Makefile b/libavformat/Makefile index f5d6b8fecf..6482f247b6 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -681,11 +681,14 @@ OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o -SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ + mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavdevice dependencies diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 31d1d93c23..66c530a2ff 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -24,6 +24,7 @@ #include "libavutil/intfloat.h" #include "libavutil/avassert.h" #include "libavutil/mathematics.h" +#include "libavcodec/mpeg4audio.h" #include "avio_internal.h" #include "avio.h" #include "avc.h" @@ -33,7 +34,6 @@ #include "metadata.h" #include "libavutil/opt.h" #include "libavcodec/put_bits.h" -#include "libavcodec/aacenctab.h" static const AVCodecTag flv_video_codec_ids[] = { @@ -514,7 +514,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i for (samplerate_index = 0; samplerate_index < 16; samplerate_index++) if (flv->audio_par->sample_rate - == mpeg4audio_sample_rates[samplerate_index]) + == ff_mpeg4audio_sample_rates[samplerate_index]) break; init_put_bits(&pbc, data, sizeof(data)); diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 6ce553205d..e271916bf1 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2029,8 +2029,8 @@ static int matroska_aac_sri(int samplerate) { int sri; - for (sri = 0; sri < FF_ARRAY_ELEMS(avpriv_mpeg4audio_sample_rates); sri++) - if (avpriv_mpeg4audio_sample_rates[sri] == samplerate) + for (sri = 0; sri < FF_ARRAY_ELEMS(ff_mpeg4audio_sample_rates); sri++) + if (ff_mpeg4audio_sample_rates[sri] == samplerate) break; return sri; } diff --git a/libavformat/mpeg4audio_sample_rates.c b/libavformat/mpeg4audio_sample_rates.c new file mode 100644 index 0000000000..212385f348 --- /dev/null +++ b/libavformat/mpeg4audio_sample_rates.c @@ -0,0 +1,23 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/mpeg4audio_sample_rates.h" diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 111a25b126..2230d74742 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -481,7 +481,7 @@ static int latm_context2config(AVFormatContext *s, const AVCodecParameters *par, *out = NULL; for (rate_index = 0; rate_index < 16; rate_index++) - if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate) + if (ff_mpeg4audio_sample_rates[rate_index] == par->sample_rate) break; if (rate_index == 16) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); From 33e6d57f01dd4742a2e25ac5fa072b487d9d02ce Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Mar 2021 12:15:35 +0100 Subject: [PATCH 705/894] avcodec/mpegaudiodata: Unavpriv mpa_bitrate and mpa_frequency tabs These arrays have a size of 180 resp. six bytes. This does not make it worthwhile to export them due to the overhead this occurs; for x64 Elf/Linux/GNU: 2x2B version, 2x24B .dynsym, 24B .rela.dyn, 8B .got, 4B hash + twice the size of the name (here 20+23B). Therefore these symbols are unavprived and duplicated for shared builds. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 16 ++++++----- libavcodec/mp3_header_decompress_bsf.c | 5 ++-- libavcodec/mpegaudiodata.c | 13 --------- libavcodec/mpegaudiodata.h | 5 ++-- libavcodec/mpegaudiodecheader.c | 6 ++-- libavcodec/mpegaudioenc_template.c | 8 +++--- libavcodec/mpegaudiotabs.c | 22 +++++++++++++++ libavcodec/mpegaudiotabs.h | 39 ++++++++++++++++++++++++++ libavformat/Makefile | 3 ++ libavformat/isom.c | 2 +- libavformat/mp3enc.c | 8 +++--- libavformat/mpegaudiotabs.c | 22 +++++++++++++++ libavformat/nutenc.c | 4 +-- 13 files changed, 114 insertions(+), 39 deletions(-) create mode 100644 libavcodec/mpegaudiotabs.c create mode 100644 libavcodec/mpegaudiotabs.h create mode 100644 libavformat/mpegaudiotabs.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 63b4952eaf..5c045a15ea 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -123,7 +123,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o -OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.o +OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ @@ -474,9 +474,11 @@ OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc_float.o mpegaudio.o \ - mpegaudiodata.o mpegaudiodsp_data.o + mpegaudiodata.o mpegaudiodsp_data.o \ + mpegaudiotabs.o OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc_fixed.o mpegaudio.o \ - mpegaudiodata.o mpegaudiodsp_data.o + mpegaudiodata.o mpegaudiodsp_data.o \ + mpegaudiotabs.o OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o @@ -990,18 +992,18 @@ OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o SHLIBOBJS += log2_tab.o reverse.o # General libavformat dependencies -OBJS-$(CONFIG_ISO_MEDIA) += mpegaudiodata.o - OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o +STLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o \ mpeg4audio_sample_rates.o @@ -1171,7 +1173,7 @@ OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \ - mpegaudiodata.o + mpegaudiotabs.o OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c index 44c174c21c..ebf6bde1c2 100644 --- a/libavcodec/mp3_header_decompress_bsf.c +++ b/libavcodec/mp3_header_decompress_bsf.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "bsf.h" #include "bsf_internal.h" +#include "defs.h" #include "mpegaudiodecheader.h" #include "mpegaudiodata.h" @@ -67,10 +68,10 @@ static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out) goto fail; } - sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off for(bitrate_index=2; bitrate_index<30; bitrate_index++){ - frame_size = avpriv_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; + frame_size = ff_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); if(frame_size == buf_size + 4) break; diff --git a/libavcodec/mpegaudiodata.c b/libavcodec/mpegaudiodata.c index 0569281109..669590908f 100644 --- a/libavcodec/mpegaudiodata.c +++ b/libavcodec/mpegaudiodata.c @@ -26,19 +26,6 @@ #include "mpegaudiodata.h" - -const uint16_t avpriv_mpa_bitrate_tab[2][3][15] = { - { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, - {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, - {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, - { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} - } -}; - -const uint16_t avpriv_mpa_freq_tab[3] = { 44100, 48000, 32000 }; - /*******************************************************/ /* layer 2 tables */ diff --git a/libavcodec/mpegaudiodata.h b/libavcodec/mpegaudiodata.h index 0a425ef6a8..a4148a1ffe 100644 --- a/libavcodec/mpegaudiodata.h +++ b/libavcodec/mpegaudiodata.h @@ -31,14 +31,13 @@ #include "config.h" -#include "internal.h" #include "vlc.h" #define MODE_EXT_MS_STEREO 2 #define MODE_EXT_I_STEREO 1 -extern av_export_avcodec const uint16_t avpriv_mpa_bitrate_tab[2][3][15]; -extern av_export_avcodec const uint16_t avpriv_mpa_freq_tab[3]; +extern const uint16_t ff_mpa_bitrate_tab[2][3][15]; +extern const uint16_t ff_mpa_freq_tab[3]; extern const int ff_mpa_sblimit_table[5]; extern const int ff_mpa_quant_steps[17]; extern const int ff_mpa_quant_bits[17]; diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c index 93c5f3d8f8..446a6e29d8 100644 --- a/libavcodec/mpegaudiodecheader.c +++ b/libavcodec/mpegaudiodecheader.c @@ -52,9 +52,9 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) s->layer = 4 - ((header >> 17) & 3); /* extract frequency */ sample_rate_index = (header >> 10) & 3; - if (sample_rate_index >= FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) + if (sample_rate_index >= FF_ARRAY_ELEMS(ff_mpa_freq_tab)) sample_rate_index = 0; - sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); sample_rate_index += 3 * (s->lsf + mpeg25); s->sample_rate_index = sample_rate_index; s->error_protection = ((header >> 16) & 1) ^ 1; @@ -75,7 +75,7 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) s->nb_channels = 2; if (bitrate_index != 0) { - frame_size = avpriv_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; + frame_size = ff_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; s->bit_rate = frame_size * 1000; switch(s->layer) { case 1: diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc_template.c index 1df3cc704a..1ffd31f7cb 100644 --- a/libavcodec/mpegaudioenc_template.c +++ b/libavcodec/mpegaudioenc_template.c @@ -95,9 +95,9 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) /* encoding freq */ s->lsf = 0; for(i=0;i<3;i++) { - if (avpriv_mpa_freq_tab[i] == freq) + if (ff_mpa_freq_tab[i] == freq) break; - if ((avpriv_mpa_freq_tab[i] / 2) == freq) { + if ((ff_mpa_freq_tab[i] / 2) == freq) { s->lsf = 1; break; } @@ -110,12 +110,12 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) /* encoding bitrate & frequency */ for(i=1;i<15;i++) { - if (avpriv_mpa_bitrate_tab[s->lsf][1][i] == bitrate) + if (ff_mpa_bitrate_tab[s->lsf][1][i] == bitrate) break; } if (i == 15 && !avctx->bit_rate) { i = 14; - bitrate = avpriv_mpa_bitrate_tab[s->lsf][1][i]; + bitrate = ff_mpa_bitrate_tab[s->lsf][1][i]; avctx->bit_rate = bitrate * 1000; } if (i == 15){ diff --git a/libavcodec/mpegaudiotabs.c b/libavcodec/mpegaudiotabs.c new file mode 100644 index 0000000000..eaa380c808 --- /dev/null +++ b/libavcodec/mpegaudiotabs.c @@ -0,0 +1,22 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mpegaudiotabs.h" diff --git a/libavcodec/mpegaudiotabs.h b/libavcodec/mpegaudiotabs.h new file mode 100644 index 0000000000..671b83848d --- /dev/null +++ b/libavcodec/mpegaudiotabs.h @@ -0,0 +1,39 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGAUDIOTABS_H +#define AVCODEC_MPEGAUDIOTABS_H + +#include + +const uint16_t ff_mpa_bitrate_tab[2][3][15] = { + { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, + { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } + } +}; + +const uint16_t ff_mpa_freq_tab[3] = { 44100, 48000, 32000 }; + +#endif diff --git a/libavformat/Makefile b/libavformat/Makefile index 6482f247b6..892189d66a 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -681,11 +681,14 @@ OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ mpeg4audio_sample_rates.o diff --git a/libavformat/isom.c b/libavformat/isom.c index 300ba927c2..015c82e1bb 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -362,7 +362,7 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext return ret; st->codecpar->channels = cfg.channels; if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 - st->codecpar->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index]; + st->codecpar->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; else if (cfg.ext_sample_rate) st->codecpar->sample_rate = cfg.ext_sample_rate; else diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 5728ef30be..0ffc79c025 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -159,8 +159,8 @@ static int mp3_write_xing(AVFormatContext *s) if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) || !mp3->write_xing) return 0; - for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) { - const uint16_t base_freq = avpriv_mpa_freq_tab[i]; + for (i = 0; i < FF_ARRAY_ELEMS(ff_mpa_freq_tab); i++) { + const uint16_t base_freq = ff_mpa_freq_tab[i]; if (par->sample_rate == base_freq) ver = 0x3; // MPEG 1 else if (par->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2 @@ -170,7 +170,7 @@ static int mp3_write_xing(AVFormatContext *s) srate_idx = i; break; } - if (i == FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) { + if (i == FF_ARRAY_ELEMS(ff_mpa_freq_tab)) { av_log(s, AV_LOG_WARNING, "Unsupported sample rate, not writing Xing header.\n"); return -1; } @@ -190,7 +190,7 @@ static int mp3_write_xing(AVFormatContext *s) header |= channels << 6; for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) { - int bit_rate = 1000 * avpriv_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx]; + int bit_rate = 1000 * ff_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx]; int error = FFABS(bit_rate - par->bit_rate); if (error < best_bitrate_error) { diff --git a/libavformat/mpegaudiotabs.c b/libavformat/mpegaudiotabs.c new file mode 100644 index 0000000000..41ac76e21b --- /dev/null +++ b/libavformat/mpegaudiotabs.c @@ -0,0 +1,22 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/mpegaudiotabs.h" diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 7977980935..585ce953ca 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -70,11 +70,11 @@ static int find_expected_header(AVCodecParameters *p, int size, int key_frame, else if (sample_rate < (44100 + 48000) / 2) sample_rate_index = 0; else sample_rate_index = 1; - sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); for (bitrate_index = 2; bitrate_index < 30; bitrate_index++) { frame_size = - avpriv_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1]; + ff_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index & 1); From 007ffbeb533af512b08851435ce78e1b15e8e1e0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 19:32:03 +0100 Subject: [PATCH 706/894] avcodec/internal: Remove unused av_export_avcodec Signed-off-by: Andreas Rheinhardt --- libavcodec/internal.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index a62f8dbd4e..d3ee0214c5 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -363,10 +363,4 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val, void ff_dvdsub_parse_palette(uint32_t *palette, const char *p); -#if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec) -# define av_export_avcodec __declspec(dllimport) -#else -# define av_export_avcodec -#endif - #endif /* AVCODEC_INTERNAL_H */ From b74e47c4ff5bca998936c0d8b9a0892104a7403d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 19:55:39 +0100 Subject: [PATCH 707/894] avcodec/utils: Unavpriv avpriv_toupper4() This function is quite small (96B with GCC 11.2 on x64 Ubuntu 21.10 at -O3), making it more economical to duplicate it into libavformat instead of exporting it as avpriv: Doing so saves 2x24B in .dynsim, 2x16B in .dynstr, 2x2B .gnu.version, 24B in .rela.plt, 16B in .plt, 16B in .plt.sec (if enabled), 4B .gnu.hash; besides the actual duplicated code this also adds 2x8B .eh_frame_hdr and 24B .eh_frame. In other words: Duplicating is neutral size-wise (it is also presumed neutral for other systems). Given that it avoids the runtime overhead of dynamic symbols, it is advantageouos to duplicate the function. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 4 +++- libavcodec/internal.h | 2 +- libavcodec/mpeg12dec.c | 2 +- libavcodec/mpegvideo.c | 2 +- libavcodec/to_upper4.c | 23 +++++++++++++++++++++++ libavcodec/to_upper4.h | 37 +++++++++++++++++++++++++++++++++++++ libavcodec/utils.c | 8 -------- libavformat/Makefile | 2 +- libavformat/movenc.c | 2 +- libavformat/mux.c | 2 +- libavformat/to_upper4.c | 23 +++++++++++++++++++++++ libavformat/utils.c | 2 +- 12 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 libavcodec/to_upper4.c create mode 100644 libavcodec/to_upper4.h create mode 100644 libavformat/to_upper4.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5c045a15ea..81a11a3688 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -127,7 +127,8 @@ OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ - mpegvideodata.o mpegpicture.o + mpegvideodata.o mpegpicture.o \ + to_upper4.o OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ motion_est.o ratecontrol.o \ mpegvideoencdsp.o @@ -996,6 +997,7 @@ OBJS-$(CONFIG_FITS_DEMUXER) += fits.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_AVFORMAT) += to_upper4.o STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o diff --git a/libavcodec/internal.h b/libavcodec/internal.h index d3ee0214c5..72ca1553f6 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -225,7 +225,7 @@ extern const uint8_t ff_log2_run[41]; */ int ff_match_2uint16(const uint16_t (*tab)[2], int size, int a, int b); -unsigned int avpriv_toupper4(unsigned int x); +unsigned int ff_toupper4(unsigned int x); void ff_color_frame(AVFrame *frame, const int color[4]); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 672031b6db..cf06af0a71 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2832,7 +2832,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, } #endif - s2->codec_tag = avpriv_toupper4(avctx->codec_tag); + s2->codec_tag = ff_toupper4(avctx->codec_tag); if (s->mpeg_enc_ctx_allocated == 0 && ( s2->codec_tag == AV_RL32("VCR2") || s2->codec_tag == AV_RL32("BW10") )) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 46e56ca08e..a974650133 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -701,7 +701,7 @@ void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) s->workaround_bugs = avctx->workaround_bugs; /* convert fourcc to upper case */ - s->codec_tag = avpriv_toupper4(avctx->codec_tag); + s->codec_tag = ff_toupper4(avctx->codec_tag); } /** diff --git a/libavcodec/to_upper4.c b/libavcodec/to_upper4.c new file mode 100644 index 0000000000..29f65bf5c3 --- /dev/null +++ b/libavcodec/to_upper4.c @@ -0,0 +1,23 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "to_upper4.h" diff --git a/libavcodec/to_upper4.h b/libavcodec/to_upper4.h new file mode 100644 index 0000000000..d9648b5ef6 --- /dev/null +++ b/libavcodec/to_upper4.h @@ -0,0 +1,37 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_TO_UPPER4_H +#define AVCODEC_TO_UPPER4_H + +#include "libavutil/avstring.h" +#include "internal.h" + +unsigned int ff_toupper4(unsigned int x) +{ + return av_toupper(x & 0xFF) | + (av_toupper((x >> 8) & 0xFF) << 8) | + (av_toupper((x >> 16) & 0xFF) << 16) | +((unsigned)av_toupper((x >> 24) & 0xFF) << 24); +} + +#endif diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 4d236ff1cd..b19befef21 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -863,14 +863,6 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) return &codec->hw_configs[index]->public; } -unsigned int avpriv_toupper4(unsigned int x) -{ - return av_toupper(x & 0xFF) + - (av_toupper((x >> 8) & 0xFF) << 8) + - (av_toupper((x >> 16) & 0xFF) << 16) + -((unsigned)av_toupper((x >> 24) & 0xFF) << 24); -} - int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) { int ret; diff --git a/libavformat/Makefile b/libavformat/Makefile index 892189d66a..8aba9d164c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -680,7 +680,7 @@ OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds -SHLIBOBJS += log2_tab.o +SHLIBOBJS += log2_tab.o to_upper4.o SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o diff --git a/libavformat/movenc.c b/libavformat/movenc.c index bc6abcfcaa..5d4429b82e 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1717,7 +1717,7 @@ static unsigned int validate_codec_tag(const AVCodecTag *const *tags, for (i = 0; tags && tags[i]; i++) { const AVCodecTag *codec_tags = tags[i]; while (codec_tags->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(codec_tags->tag) == avpriv_toupper4(tag) && + if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) && codec_tags->id == codec_id) return codec_tags->tag; codec_tags++; diff --git a/libavformat/mux.c b/libavformat/mux.c index 3ba95d28c6..0500f636de 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -204,7 +204,7 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st) for (int n = 0; s->oformat->codec_tag[n]; n++) { avctag = s->oformat->codec_tag[n]; while (avctag->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codecpar->codec_tag)) { + if (ff_toupper4(avctag->tag) == ff_toupper4(st->codecpar->codec_tag)) { id = avctag->id; if (id == st->codecpar->codec_id) return 1; diff --git a/libavformat/to_upper4.c b/libavformat/to_upper4.c new file mode 100644 index 0000000000..e84c803675 --- /dev/null +++ b/libavformat/to_upper4.c @@ -0,0 +1,23 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/to_upper4.h" diff --git a/libavformat/utils.c b/libavformat/utils.c index 23e81bda9d..ca6185b5c3 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -361,7 +361,7 @@ enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) if (tag == tags[i].tag) return tags[i].id; for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) - if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag)) + if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) return tags[i].id; return AV_CODEC_ID_NONE; } From d61240f8c95e9cf7a0aaef2bb4495960d3fec62c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 16 Dec 2021 01:49:39 +0100 Subject: [PATCH 708/894] avcodec/packet_internal: Add proper PacketList struct Up until now, we had a PacketList structure which is actually a PacketListEntry; a proper PacketList did not exist and all the related functions just passed pointers to pointers to the head and tail elements around. All these pointers were actually consecutive elements of their containing structs, i.e. the users already treated them as if they were a struct. So add a proper PacketList struct and rename the current PacketList to PacketListEntry; also make the functions use this structure instead of the pair of pointers. Signed-off-by: Andreas Rheinhardt --- libavcodec/avpacket.c | 36 +++++++++++------------ libavcodec/packet_internal.h | 25 +++++++--------- libavdevice/decklink_common.h | 5 +++- libavdevice/decklink_dec.cpp | 29 +++++++++---------- libavdevice/dshow.c | 10 +++---- libavdevice/dshow_capture.h | 2 +- libavdevice/vfwcap.c | 12 ++++---- libavformat/aiffenc.c | 17 ++++++----- libavformat/demux.c | 54 ++++++++++++++++------------------- libavformat/flacenc.c | 10 +++---- libavformat/internal.h | 12 ++++---- libavformat/matroskadec.c | 19 ++++++------ libavformat/movenc.c | 6 ++-- libavformat/movenc.h | 2 +- libavformat/movenc_ttml.c | 6 ++-- libavformat/mp3enc.c | 11 ++++--- libavformat/mux.c | 38 ++++++++++++------------ libavformat/mxfenc.c | 14 ++++----- libavformat/ttaenc.c | 13 ++++----- libavformat/utils.c | 7 ++--- 20 files changed, 153 insertions(+), 175 deletions(-) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index a0134e405c..4f7a6b255c 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -535,13 +535,12 @@ void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); } -int avpriv_packet_list_put(PacketList **packet_buffer, - PacketList **plast_pktl, +int avpriv_packet_list_put(PacketList *packet_buffer, AVPacket *pkt, int (*copy)(AVPacket *dst, const AVPacket *src), int flags) { - PacketList *pktl = av_malloc(sizeof(PacketList)); + PacketListEntry *pktl = av_malloc(sizeof(*pktl)); int ret; if (!pktl) @@ -565,44 +564,41 @@ int avpriv_packet_list_put(PacketList **packet_buffer, pktl->next = NULL; - if (*packet_buffer) - (*plast_pktl)->next = pktl; + if (packet_buffer->head) + packet_buffer->tail->next = pktl; else - *packet_buffer = pktl; + packet_buffer->head = pktl; /* Add the packet in the buffered packet list. */ - *plast_pktl = pktl; + packet_buffer->tail = pktl; return 0; } -int avpriv_packet_list_get(PacketList **pkt_buffer, - PacketList **pkt_buffer_end, +int avpriv_packet_list_get(PacketList *pkt_buffer, AVPacket *pkt) { - PacketList *pktl; - if (!*pkt_buffer) + PacketListEntry *pktl = pkt_buffer->head; + if (!pktl) return AVERROR(EAGAIN); - pktl = *pkt_buffer; *pkt = pktl->pkt; - *pkt_buffer = pktl->next; - if (!pktl->next) - *pkt_buffer_end = NULL; + pkt_buffer->head = pktl->next; + if (!pkt_buffer->head) + pkt_buffer->tail = NULL; av_freep(&pktl); return 0; } -void avpriv_packet_list_free(PacketList **pkt_buf, PacketList **pkt_buf_end) +void avpriv_packet_list_free(PacketList *pkt_buf) { - PacketList *tmp = *pkt_buf; + PacketListEntry *tmp = pkt_buf->head; while (tmp) { - PacketList *pktl = tmp; + PacketListEntry *pktl = tmp; tmp = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); } - *pkt_buf = NULL; - *pkt_buf_end = NULL; + pkt_buf->head = pkt_buf->tail = NULL; } int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type) diff --git a/libavcodec/packet_internal.h b/libavcodec/packet_internal.h index a10931c106..92a0d4e6d5 100644 --- a/libavcodec/packet_internal.h +++ b/libavcodec/packet_internal.h @@ -23,16 +23,19 @@ #include "packet.h" -typedef struct PacketList { - struct PacketList *next; +typedef struct PacketListEntry { + struct PacketListEntry *next; AVPacket pkt; +} PacketListEntry; + +typedef struct PacketList { + PacketListEntry *head, *tail; } PacketList; /** * Append an AVPacket to the list. * - * @param head List head element - * @param tail List tail element + * @param list A PacketList * @param pkt The packet being appended. The data described in it will * be made reference counted if it isn't already. * @param copy A callback to copy the contents of the packet to the list. @@ -41,8 +44,7 @@ typedef struct PacketList { * @return 0 on success, negative AVERROR value on failure. On failure, the packet and the list are unchanged. */ -int avpriv_packet_list_put(PacketList **head, PacketList **tail, - AVPacket *pkt, +int avpriv_packet_list_put(PacketList *list, AVPacket *pkt, int (*copy)(AVPacket *dst, const AVPacket *src), int flags); @@ -52,22 +54,17 @@ int avpriv_packet_list_put(PacketList **head, PacketList **tail, * @note The pkt will be overwritten completely on success. The caller * owns the packet and must unref it by itself. * - * @param head List head element - * @param tail List tail element + * @param head A pointer to a PacketList struct * @param pkt Pointer to an AVPacket struct * @return 0 on success, and a packet is returned. AVERROR(EAGAIN) if * the list was empty. */ -int avpriv_packet_list_get(PacketList **head, PacketList **tail, - AVPacket *pkt); +int avpriv_packet_list_get(PacketList *list, AVPacket *pkt); /** * Wipe the list and unref all the packets in it. - * - * @param head List head element - * @param tail List tail element */ -void avpriv_packet_list_free(PacketList **head, PacketList **tail); +void avpriv_packet_list_free(PacketList *list); int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type); diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 5b11dcd46d..79d6ac5b38 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -29,6 +29,9 @@ #define IDeckLinkProfileAttributes IDeckLinkAttributes #endif +extern "C" { +#include "libavcodec/packet_internal.h" +} #include "libavutil/thread.h" #include "decklink_common_c.h" #if CONFIG_LIBKLVANC @@ -75,7 +78,7 @@ class decklink_output_callback; class decklink_input_callback; typedef struct AVPacketQueue { - PacketList *first_pkt, *last_pkt; + PacketList pkt_list; int nb_packets; unsigned long long size; int abort_request; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 491fe4be3d..c97a72d93d 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -483,16 +483,16 @@ static void avpacket_queue_init(AVFormatContext *avctx, AVPacketQueue *q) static void avpacket_queue_flush(AVPacketQueue *q) { - PacketList *pkt, *pkt1; + PacketListEntry *pkt, *pkt1; pthread_mutex_lock(&q->mutex); - for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) { + for (pkt = q->pkt_list.head; pkt != NULL; pkt = pkt1) { pkt1 = pkt->next; av_packet_unref(&pkt->pkt); av_freep(&pkt); } - q->last_pkt = NULL; - q->first_pkt = NULL; + q->pkt_list.head = NULL; + q->pkt_list.tail = NULL; q->nb_packets = 0; q->size = 0; pthread_mutex_unlock(&q->mutex); @@ -516,7 +516,7 @@ static unsigned long long avpacket_queue_size(AVPacketQueue *q) static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) { - PacketList *pkt1; + PacketListEntry *pkt1; // Drop Packet if queue size is > maximum queue size if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) { @@ -530,7 +530,7 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) return -1; } - pkt1 = (PacketList *)av_malloc(sizeof(PacketList)); + pkt1 = (PacketListEntry *)av_malloc(sizeof(*pkt1)); if (!pkt1) { av_packet_unref(pkt); return -1; @@ -540,13 +540,13 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) pthread_mutex_lock(&q->mutex); - if (!q->last_pkt) { - q->first_pkt = pkt1; + if (!q->pkt_list.tail) { + q->pkt_list.head = pkt1; } else { - q->last_pkt->next = pkt1; + q->pkt_list.tail->next = pkt1; } - q->last_pkt = pkt1; + q->pkt_list.tail = pkt1; q->nb_packets++; q->size += pkt1->pkt.size + sizeof(*pkt1); @@ -558,17 +558,16 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block) { - PacketList *pkt1; int ret; pthread_mutex_lock(&q->mutex); for (;; ) { - pkt1 = q->first_pkt; + PacketListEntry *pkt1 = q->pkt_list.head; if (pkt1) { - q->first_pkt = pkt1->next; - if (!q->first_pkt) { - q->last_pkt = NULL; + q->pkt_list.head = pkt1->next; + if (!q->pkt_list.head) { + q->pkt_list.tail = NULL; } q->nb_packets--; q->size -= pkt1->pkt.size + sizeof(*pkt1); diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 7e04880b38..3a16f3720f 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -238,7 +238,7 @@ static int dshow_read_close(AVFormatContext *s) { struct dshow_ctx *ctx = s->priv_data; - PacketList *pktl; + PacketListEntry *pktl; if (ctx->control) { IMediaControl_Stop(ctx->control); @@ -298,7 +298,7 @@ dshow_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -342,7 +342,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, e { AVFormatContext *s = priv_data; struct dshow_ctx *ctx = s->priv_data; - PacketList **ppktl, *pktl_next; + PacketListEntry **ppktl, *pktl_next; // dump_videohdr(s, vdhdr); @@ -351,7 +351,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, e if(shall_we_drop(s, index, devtype)) goto fail; - pktl_next = av_mallocz(sizeof(PacketList)); + pktl_next = av_mallocz(sizeof(*pktl_next)); if(!pktl_next) goto fail; @@ -1868,7 +1868,7 @@ static int dshow_check_event_queue(IMediaEvent *media_event) static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt) { struct dshow_ctx *ctx = s->priv_data; - PacketList *pktl = NULL; + PacketListEntry *pktl = NULL; while (!ctx->eof && !pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 21f5cf7e83..b548cd7afc 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -322,7 +322,7 @@ struct dshow_ctx { HANDLE mutex; HANDLE event[2]; /* event[0] is set by DirectShow * event[1] is set by callback() */ - PacketList *pktl; + PacketListEntry *pktl; int eof; diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index 6fad466f8a..86a40b4af4 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -45,7 +45,7 @@ struct vfw_ctx { HWND hwnd; HANDLE mutex; HANDLE event; - PacketList *pktl; + PacketListEntry *pktl; unsigned int curbufsize; unsigned int frame_num; char *video_size; /**< A string describing video size, set by a private option. */ @@ -179,7 +179,7 @@ static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr) { AVFormatContext *s; struct vfw_ctx *ctx; - PacketList **ppktl, *pktl_next; + PacketListEntry **ppktl, *pktl_next; s = (AVFormatContext *) GetWindowLongPtr(hwnd, GWLP_USERDATA); ctx = s->priv_data; @@ -191,7 +191,7 @@ static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr) WaitForSingleObject(ctx->mutex, INFINITE); - pktl_next = av_mallocz(sizeof(PacketList)); + pktl_next = av_mallocz(sizeof(*pktl_next)); if(!pktl_next) goto fail; @@ -220,7 +220,7 @@ fail: static int vfw_read_close(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; - PacketList *pktl; + PacketListEntry *pktl; if(ctx->hwnd) { SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); @@ -234,7 +234,7 @@ static int vfw_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -440,7 +440,7 @@ fail: static int vfw_read_packet(AVFormatContext *s, AVPacket *pkt) { struct vfw_ctx *ctx = s->priv_data; - PacketList *pktl = NULL; + PacketListEntry *pktl = NULL; while(!pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 7bb0978a53..1fd6b8a70b 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -37,7 +37,7 @@ typedef struct AIFFOutputContext { int64_t frames; int64_t ssnd; int audio_stream_idx; - PacketList *pict_list, *pict_list_end; + PacketList pict_list; int write_id3v2; int id3v2_version; } AIFFOutputContext; @@ -48,9 +48,9 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff) uint64_t pos, end, size; ID3v2EncContext id3v2 = { 0 }; AVIOContext *pb = s->pb; - PacketList *pict_list = aiff->pict_list; + PacketListEntry *list_entry = aiff->pict_list.head; - if (!s->metadata && !s->nb_chapters && !aiff->pict_list) + if (!s->metadata && !s->nb_chapters && !list_entry) return 0; avio_wl32(pb, MKTAG('I', 'D', '3', ' ')); @@ -59,10 +59,10 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff) ff_id3v2_start(&id3v2, pb, aiff->id3v2_version, ID3v2_DEFAULT_MAGIC); ff_id3v2_write_metadata(s, &id3v2); - while (pict_list) { - if ((ret = ff_id3v2_write_apic(s, &id3v2, &pict_list->pkt)) < 0) + while (list_entry) { + if ((ret = ff_id3v2_write_apic(s, &id3v2, &list_entry->pkt)) < 0) return ret; - pict_list = pict_list->next; + list_entry = list_entry->next; } ff_id3v2_finish(&id3v2, pb, s->metadata_header_padding); @@ -218,8 +218,7 @@ static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt) if (s->streams[pkt->stream_index]->nb_frames >= 1) return 0; - return avpriv_packet_list_put(&aiff->pict_list, &aiff->pict_list_end, - pkt, NULL, 0); + return avpriv_packet_list_put(&aiff->pict_list, pkt, NULL, 0); } return 0; @@ -265,7 +264,7 @@ static void aiff_deinit(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; - avpriv_packet_list_free(&aiff->pict_list, &aiff->pict_list_end); + avpriv_packet_list_free(&aiff->pict_list); } #define OFFSET(x) offsetof(AIFFOutputContext, x) diff --git a/libavformat/demux.c b/libavformat/demux.c index 4770e5517f..f895f0ba85 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -537,7 +537,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif for (;;) { - PacketList *pktl = si->raw_packet_buffer; + PacketListEntry *pktl = si->raw_packet_buffer.head; AVStream *st; FFStream *sti; const AVPacket *pkt1; @@ -548,8 +548,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if ((err = probe_codec(s, st, NULL)) < 0) return err; if (ffstream(st)->request_probe <= 0) { - avpriv_packet_list_get(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, pkt); + avpriv_packet_list_get(&si->raw_packet_buffer, pkt); si->raw_packet_buffer_size -= pkt->size; return 0; } @@ -624,13 +623,12 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; err = avpriv_packet_list_put(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return err; } - pkt1 = &si->raw_packet_buffer_end->pkt; + pkt1 = &si->raw_packet_buffer.tail->pkt; si->raw_packet_buffer_size += pkt1->size; if ((err = probe_codec(s, st, pkt1)) < 0) @@ -716,13 +714,14 @@ static int has_decode_delay_been_guessed(AVStream *st) return sti->nb_decoded_frames >= 20; } -static PacketList *get_next_pkt(AVFormatContext *s, AVStream *st, PacketList *pktl) +static PacketListEntry *get_next_pkt(AVFormatContext *s, AVStream *st, + PacketListEntry *pktl) { FFFormatContext *const si = ffformatcontext(s); if (pktl->next) return pktl->next; - if (pktl == si->packet_buffer_end) - return si->parse_queue; + if (pktl == si->packet_buffer.tail) + return si->parse_queue.head; return NULL; } @@ -774,7 +773,7 @@ static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t * of the packets in a window. */ static void update_dts_from_pts(AVFormatContext *s, int stream_index, - PacketList *pkt_buffer) + PacketListEntry *pkt_buffer) { AVStream *const st = s->streams[stream_index]; int delay = ffstream(st)->avctx->has_b_frames; @@ -804,7 +803,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, FFFormatContext *const si = ffformatcontext(s); AVStream *const st = s->streams[stream_index]; FFStream *const sti = ffstream(st); - PacketList *pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + PacketListEntry *pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; uint64_t shift; @@ -823,7 +822,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, if (is_relative(pts)) pts += shift; - for (PacketList *pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) { + for (PacketListEntry *pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) { if (pktl_it->pkt.stream_index != stream_index) continue; if (is_relative(pktl_it->pkt.pts)) @@ -856,7 +855,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, { FFFormatContext *const si = ffformatcontext(s); FFStream *const sti = ffstream(st); - PacketList *pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + PacketListEntry *pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; int64_t cur_dts = RELATIVE_TS_BASE; if (sti->first_dts != AV_NOPTS_VALUE) { @@ -882,7 +881,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, av_log(s, AV_LOG_DEBUG, "first_dts %s but no packet with dts in the queue\n", av_ts2str(sti->first_dts)); return; } - pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; sti->first_dts = cur_dts; } else if (sti->cur_dts != RELATIVE_TS_BASE) return; @@ -998,7 +997,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } - if (pkt->duration > 0 && (si->packet_buffer || si->parse_queue)) + if (pkt->duration > 0 && (si->packet_buffer.head || si->parse_queue.head)) update_initial_durations(s, st, pkt->stream_index, pkt->duration); /* Correct timestamps with byte offset if demuxers only have timestamps @@ -1195,7 +1194,6 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, compute_pkt_fields(s, st, sti->parser, out_pkt, next_dts, next_pts); ret = avpriv_packet_list_put(&si->parse_queue, - &si->parse_queue_end, out_pkt, NULL, 0); if (ret < 0) goto fail; @@ -1225,7 +1223,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) int ret, got_packet = 0; AVDictionary *metadata = NULL; - while (!got_packet && !si->parse_queue) { + while (!got_packet && !si->parse_queue.head) { AVStream *st; FFStream *sti; @@ -1338,8 +1336,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) } } - if (!got_packet && si->parse_queue) - ret = avpriv_packet_list_get(&si->parse_queue, &si->parse_queue_end, pkt); + if (!got_packet && si->parse_queue.head) + ret = avpriv_packet_list_get(&si->parse_queue, pkt); if (ret >= 0) { AVStream *const st = s->streams[pkt->stream_index]; @@ -1420,9 +1418,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) AVStream *st; if (!genpts) { - ret = si->packet_buffer - ? avpriv_packet_list_get(&si->packet_buffer, - &si->packet_buffer_end, pkt) + ret = si->packet_buffer.head + ? avpriv_packet_list_get(&si->packet_buffer, pkt) : read_frame_internal(s, pkt); if (ret < 0) return ret; @@ -1430,7 +1427,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } for (;;) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; if (pktl) { AVPacket *next_pkt = &pktl->pkt; @@ -1463,15 +1460,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) // 3. the packets for this stream at the end of the files had valid dts. next_pkt->pts = last_dts + next_pkt->duration; } - pktl = si->packet_buffer; + pktl = si->packet_buffer.head; } /* read packet from packet buffer, if there is data */ st = s->streams[next_pkt->stream_index]; if (!(next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL && next_pkt->dts != AV_NOPTS_VALUE && !eof)) { - ret = avpriv_packet_list_get(&si->packet_buffer, - &si->packet_buffer_end, pkt); + ret = avpriv_packet_list_get(&si->packet_buffer, pkt); goto return_packet; } } @@ -1486,7 +1482,6 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } ret = avpriv_packet_list_put(&si->packet_buffer, - &si->packet_buffer_end, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); @@ -2598,12 +2593,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { ret = avpriv_packet_list_put(&si->packet_buffer, - &si->packet_buffer_end, pkt1, NULL, 0); if (ret < 0) goto unref_then_goto_end; - pkt = &si->packet_buffer_end->pkt; + pkt = &si->packet_buffer.tail->pkt; } else { pkt = pkt1; } @@ -2751,8 +2745,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) // EOF already reached while reading the stream above. // So continue with reoordering DTS with whatever delay we have. - if (si->packet_buffer && !has_decode_delay_been_guessed(st)) { - update_dts_from_pts(ic, stream_index, si->packet_buffer); + if (si->packet_buffer.head && !has_decode_delay_been_guessed(st)) { + update_dts_from_pts(ic, stream_index, si->packet_buffer.head); } } } diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index e8f043729e..b267197ccc 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -40,7 +40,7 @@ typedef struct FlacMuxerContext { int audio_stream_idx; int waiting_pics; /* audio packets are queued here until we get all the attached pictures */ - PacketList *queue, *queue_end; + PacketList queue; /* updated streaminfo sent by the encoder at the end */ uint8_t streaminfo[FLAC_STREAMINFO_SIZE]; @@ -306,8 +306,8 @@ static int flac_queue_flush(AVFormatContext *s) if (ret < 0) write = 0; - while (c->queue) { - avpriv_packet_list_get(&c->queue, &c->queue_end, pkt); + while (c->queue.head) { + avpriv_packet_list_get(&c->queue, pkt); if (write && (ret = flac_write_audio_packet(s, pkt)) < 0) write = 0; av_packet_unref(pkt); @@ -347,7 +347,7 @@ static void flac_deinit(struct AVFormatContext *s) { FlacMuxerContext *c = s->priv_data; - avpriv_packet_list_free(&c->queue, &c->queue_end); + avpriv_packet_list_free(&c->queue); for (unsigned i = 0; i < s->nb_streams; i++) av_packet_free((AVPacket **)&s->streams[i]->priv_data); } @@ -360,7 +360,7 @@ static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == c->audio_stream_idx) { if (c->waiting_pics) { /* buffer audio packets until we get all the pictures */ - ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, NULL, 0); + ret = avpriv_packet_list_put(&c->queue, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); c->waiting_pics = 0; diff --git a/libavformat/internal.h b/libavformat/internal.h index 63235ce5cf..bffb8e66ff 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -25,6 +25,7 @@ #include "libavcodec/avcodec.h" #include "libavcodec/bsf.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "os_support.h" @@ -92,8 +93,7 @@ typedef struct FFFormatContext { * not decoded, for example to get the codec parameters in MPEG * streams. */ - struct PacketList *packet_buffer; - struct PacketList *packet_buffer_end; + PacketList packet_buffer; /* av_seek_frame() support */ int64_t data_offset; /**< offset of the first packet */ @@ -104,13 +104,11 @@ typedef struct FFFormatContext { * be identified, as parsing cannot be done without knowing the * codec. */ - struct PacketList *raw_packet_buffer; - struct PacketList *raw_packet_buffer_end; + PacketList raw_packet_buffer; /** * Packets split by the parser get queued here. */ - struct PacketList *parse_queue; - struct PacketList *parse_queue_end; + PacketList parse_queue; /** * The generic code uses this as a temporary packet * to parse packets or for muxing, especially flushing. @@ -393,7 +391,7 @@ typedef struct FFStream { /** * last packet in packet_buffer for this stream when muxing. */ - struct PacketList *last_in_packet_buffer; + PacketListEntry *last_in_packet_buffer; int64_t last_IP_pts; int last_IP_duration; diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index e271916bf1..78e5a4a203 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -396,8 +396,7 @@ typedef struct MatroskaDemuxContext { AVPacket *pkt; /* the packet queue */ - PacketList *queue; - PacketList *queue_end; + PacketList queue; int done; @@ -3112,11 +3111,11 @@ static int matroska_read_header(AVFormatContext *s) static int matroska_deliver_packet(MatroskaDemuxContext *matroska, AVPacket *pkt) { - if (matroska->queue) { + if (matroska->queue.head) { MatroskaTrack *tracks = matroska->tracks.elem; MatroskaTrack *track; - avpriv_packet_list_get(&matroska->queue, &matroska->queue_end, pkt); + avpriv_packet_list_get(&matroska->queue, pkt); track = &tracks[pkt->stream_index]; if (track->has_palette) { uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); @@ -3138,7 +3137,7 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, */ static void matroska_clear_queue(MatroskaDemuxContext *matroska) { - avpriv_packet_list_free(&matroska->queue, &matroska->queue_end); + avpriv_packet_list_free(&matroska->queue); } static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, @@ -3304,7 +3303,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, track->audio.buf_timecode = AV_NOPTS_VALUE; pkt->pos = pos; pkt->stream_index = st->index; - ret = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + ret = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3526,7 +3525,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, pkt->duration = duration; pkt->pos = pos; - err = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + err = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3628,7 +3627,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt->pos = pos; pkt->duration = lace_duration; - res = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + res = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (res < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -4030,10 +4029,10 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s) matroska_reset_status(matroska, 0, cluster_pos); matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0 || - !matroska->queue) { + !matroska->queue.head) { break; } - pkt = &matroska->queue->pkt; + pkt = &matroska->queue.head->pkt; // 4 + read is the length of the cluster id and the cluster length field. cluster_pos += 4 + read + cluster_length; if (!(pkt->flags & AV_PKT_FLAG_KEY)) { diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 5d4429b82e..ab33371296 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -5339,7 +5339,7 @@ static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track) switch (track->st->codecpar->codec_id) { case AV_CODEC_ID_TTML: { - int had_packets = !!track->squashed_packet_queue; + int had_packets = !!track->squashed_packet_queue.head; if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) { goto finish_squash; @@ -6190,7 +6190,6 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) /* The following will reset pkt and is only allowed to be used * because we return immediately. afterwards. */ if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue, - &trk->squashed_packet_queue_end, pkt, NULL, 0)) < 0) { return ret; } @@ -6478,8 +6477,7 @@ static void mov_free(AVFormatContext *s) ff_mov_cenc_free(&track->cenc); ffio_free_dyn_buf(&track->mdat_buf); - avpriv_packet_list_free(&track->squashed_packet_queue, - &track->squashed_packet_queue_end); + avpriv_packet_list_free(&track->squashed_packet_queue); } av_freep(&mov->tracks); diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 40077b1afe..2ac84ed070 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -167,7 +167,7 @@ typedef struct MOVTrack { unsigned int squash_fragment_samples_to_one; //< flag to note formats where all samples for a fragment are to be squashed - PacketList *squashed_packet_queue, *squashed_packet_queue_end; + PacketList squashed_packet_queue; } MOVTrack; typedef enum { diff --git a/libavformat/movenc_ttml.c b/libavformat/movenc_ttml.c index 472572b45a..6deae49657 100644 --- a/libavformat/movenc_ttml.c +++ b/libavformat/movenc_ttml.c @@ -70,9 +70,7 @@ static int mov_write_ttml_document_from_queue(AVFormatContext *s, return ret; } - while (!avpriv_packet_list_get(&track->squashed_packet_queue, - &track->squashed_packet_queue_end, - pkt)) { + while (!avpriv_packet_list_get(&track->squashed_packet_queue, pkt)) { end_ts = FFMAX(end_ts, pkt->pts + pkt->duration); // in case of the 'dfxp' muxing mode, each written document is offset @@ -121,7 +119,7 @@ int ff_mov_generate_squashed_ttml_packet(AVFormatContext *s, goto cleanup; } - if (!track->squashed_packet_queue) { + if (!track->squashed_packet_queue.head) { // empty queue, write minimal empty document with zero duration avio_write(ttml_ctx->pb, empty_ttml_document, sizeof(empty_ttml_document) - 1); diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 0ffc79c025..3ff19da274 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -132,7 +132,7 @@ typedef struct MP3Context { int pics_to_write; /* audio packets are queued here until we get all the attached pictures */ - PacketList *queue, *queue_end; + PacketList queue; } MP3Context; static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}}; @@ -387,8 +387,8 @@ static int mp3_queue_flush(AVFormatContext *s) ff_id3v2_finish(&mp3->id3, s->pb, s->metadata_header_padding); mp3_write_xing(s); - while (mp3->queue) { - avpriv_packet_list_get(&mp3->queue, &mp3->queue_end, pkt); + while (mp3->queue.head) { + avpriv_packet_list_get(&mp3->queue, pkt); if (write && (ret = mp3_write_audio_packet(s, pkt)) < 0) write = 0; av_packet_unref(pkt); @@ -524,8 +524,7 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, - pkt, NULL, 0); + int ret = avpriv_packet_list_put(&mp3->queue, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); @@ -633,7 +632,7 @@ static void mp3_deinit(struct AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - avpriv_packet_list_free(&mp3->queue, &mp3->queue_end); + avpriv_packet_list_free(&mp3->queue); av_freep(&mp3->xing_frame); } diff --git a/libavformat/mux.c b/libavformat/mux.c index 0500f636de..c387f8ec6e 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -809,12 +809,12 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, { int ret; FFFormatContext *const si = ffformatcontext(s); - PacketList **next_point, *this_pktl; + PacketListEntry **next_point, *this_pktl; AVStream *st = s->streams[pkt->stream_index]; FFStream *const sti = ffstream(st); int chunked = s->max_chunk_size || s->max_chunk_duration; - this_pktl = av_malloc(sizeof(PacketList)); + this_pktl = av_malloc(sizeof(*this_pktl)); if (!this_pktl) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -831,7 +831,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (sti->last_in_packet_buffer) { next_point = &(sti->last_in_packet_buffer->next); } else { - next_point = &si->packet_buffer; + next_point = &si->packet_buffer.head; } if (chunked) { @@ -855,7 +855,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (chunked && !(pkt->flags & CHUNK_START)) goto next_non_null; - if (compare(s, &si->packet_buffer_end->pkt, pkt)) { + if (compare(s, &si->packet_buffer.tail->pkt, pkt)) { while ( *next_point && ((chunked && !((*next_point)->pkt.flags&CHUNK_START)) || !compare(s, &(*next_point)->pkt, pkt))) @@ -863,12 +863,12 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (*next_point) goto next_non_null; } else { - next_point = &(si->packet_buffer_end->next); + next_point = &(si->packet_buffer.tail->next); } } av_assert1(!*next_point); - si->packet_buffer_end = this_pktl; + si->packet_buffer.tail = this_pktl; next_non_null: this_pktl->next = *next_point; @@ -939,11 +939,11 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, flush = 1; if (s->max_interleave_delta > 0 && - si->packet_buffer && + si->packet_buffer.head && !flush && si->nb_interleaved_streams == stream_count+noninterleaved_count ) { - AVPacket *const top_pkt = &si->packet_buffer->pkt; + AVPacket *const top_pkt = &si->packet_buffer.head->pkt; int64_t delta_dts = INT64_MIN; int64_t top_dts = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -952,7 +952,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, for (unsigned i = 0; i < s->nb_streams; i++) { const AVStream *const st = s->streams[i]; const FFStream *const sti = cffstream(st); - const PacketList *last = sti->last_in_packet_buffer; + const PacketListEntry *const last = sti->last_in_packet_buffer; int64_t last_dts; if (!last) @@ -973,11 +973,11 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } } - if (si->packet_buffer && + if (si->packet_buffer.head && eof && (s->flags & AVFMT_FLAG_SHORTEST) && si->shortest_end == AV_NOPTS_VALUE) { - AVPacket *const top_pkt = &si->packet_buffer->pkt; + AVPacket *const top_pkt = &si->packet_buffer.head->pkt; si->shortest_end = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -985,8 +985,8 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } if (si->shortest_end != AV_NOPTS_VALUE) { - while (si->packet_buffer) { - PacketList *pktl = si->packet_buffer; + while (si->packet_buffer.head) { + PacketListEntry *pktl = si->packet_buffer.head; AVPacket *const top_pkt = &pktl->pkt; AVStream *const st = s->streams[top_pkt->stream_index]; FFStream *const sti = ffstream(st); @@ -996,9 +996,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, if (si->shortest_end + 1 >= top_dts) break; - si->packet_buffer = pktl->next; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; + si->packet_buffer.head = pktl->next; + if (!si->packet_buffer.head) + si->packet_buffer.tail = NULL; if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; @@ -1010,13 +1010,13 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } if (stream_count && flush) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; AVStream *const st = s->streams[pktl->pkt.stream_index]; FFStream *const sti = ffstream(st); if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; - avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, pkt); + avpriv_packet_list_get(&si->packet_buffer, pkt); return 1; } else { @@ -1049,7 +1049,7 @@ int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) { FFFormatContext *const si = ffformatcontext(s); - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; while (pktl) { if (pktl->pkt.stream_index == stream) { return &pktl->pkt; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 4c02e3e264..5e068c8220 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -3097,9 +3097,9 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus stream_count += !!ffstream(s->streams[i])->last_in_packet_buffer; if (stream_count && (s->nb_streams == stream_count || flush)) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; if (s->nb_streams != stream_count) { - PacketList *last = NULL; + PacketListEntry *last = NULL; // find last packet in edit unit while (pktl) { if (!stream_count || pktl->pkt.stream_index == 0) @@ -3113,7 +3113,7 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus } // purge packet queue while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); pktl = next; @@ -3121,16 +3121,16 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus if (last) last->next = NULL; else { - si->packet_buffer = NULL; - si->packet_buffer_end = NULL; + si->packet_buffer.head = NULL; + si->packet_buffer.tail = NULL; goto out; } - pktl = si->packet_buffer; + pktl = si->packet_buffer.head; } if (ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer == pktl) ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer = NULL; - avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, out); + avpriv_packet_list_get(&si->packet_buffer, out); av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", out->stream_index, out->dts); return 1; } else { diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 5f21fdc144..486f8bdd10 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -30,7 +30,7 @@ typedef struct TTAMuxContext { AVIOContext *seek_table; - PacketList *queue, *queue_end; + PacketList queue; uint32_t nb_samples; int frame_size; int last_frame; @@ -94,12 +94,11 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) TTAMuxContext *tta = s->priv_data; int ret; - ret = avpriv_packet_list_put(&tta->queue, &tta->queue_end, pkt, - NULL, 0); + ret = avpriv_packet_list_put(&tta->queue, pkt, NULL, 0); if (ret < 0) { return ret; } - pkt = &tta->queue_end->pkt; + pkt = &tta->queue.tail->pkt; avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; @@ -126,8 +125,8 @@ static void tta_queue_flush(AVFormatContext *s) TTAMuxContext *tta = s->priv_data; AVPacket *const pkt = ffformatcontext(s)->pkt; - while (tta->queue) { - avpriv_packet_list_get(&tta->queue, &tta->queue_end, pkt); + while (tta->queue.head) { + avpriv_packet_list_get(&tta->queue, pkt); avio_write(s->pb, pkt->data, pkt->size); av_packet_unref(pkt); } @@ -163,7 +162,7 @@ static void tta_deinit(AVFormatContext *s) TTAMuxContext *tta = s->priv_data; ffio_free_dyn_buf(&tta->seek_table); - avpriv_packet_list_free(&tta->queue, &tta->queue_end); + avpriv_packet_list_free(&tta->queue); } const AVOutputFormat ff_tta_muxer = { diff --git a/libavformat/utils.c b/libavformat/utils.c index ca6185b5c3..e643821fc9 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -239,7 +239,6 @@ int avformat_queue_attached_pictures(AVFormatContext *s) } ret = avpriv_packet_list_put(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, &s->streams[i]->attached_pic, av_packet_ref, 0); if (ret < 0) @@ -300,9 +299,9 @@ int ff_is_intra_only(enum AVCodecID id) void ff_flush_packet_queue(AVFormatContext *s) { FFFormatContext *const si = ffformatcontext(s); - avpriv_packet_list_free(&si->parse_queue, &si->parse_queue_end); - avpriv_packet_list_free(&si->packet_buffer, &si->packet_buffer_end); - avpriv_packet_list_free(&si->raw_packet_buffer, &si->raw_packet_buffer_end); + avpriv_packet_list_free(&si->parse_queue); + avpriv_packet_list_free(&si->packet_buffer); + avpriv_packet_list_free(&si->raw_packet_buffer); si->raw_packet_buffer_size = 0; } From c512be9a908204d9ac99556b908140b10a2dc13e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 13:40:03 +0100 Subject: [PATCH 709/894] lib*/version.h: Bump Versions before release/5.0 branch Signed-off-by: Andreas Rheinhardt --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 7a8852bf15..4d77431842 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 17 +#define LIBAVCODEC_VERSION_MINOR 18 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index add4d4228a..75e3378117 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 3 +#define LIBAVDEVICE_VERSION_MINOR 4 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index c76f6d22e2..1a1d7ee1cc 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 23 +#define LIBAVFILTER_VERSION_MINOR 24 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index e8873c8925..c53d9a6444 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 15 +#define LIBAVFORMAT_VERSION_MINOR 16 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index d257e5438d..58c617975d 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 16 +#define LIBAVUTIL_VERSION_MINOR 17 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index 33fd0479b1..0c8db478de 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 2 +#define LIBPOSTPROC_VERSION_MINOR 3 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 1a786c6a1d..d6fb8c3e24 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 2 +#define LIBSWRESAMPLE_VERSION_MINOR 3 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index aaaf6edc32..24448248e5 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 3 +#define LIBSWSCALE_VERSION_MINOR 4 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From b189550137155a622f88df6e64e72c2cca660854 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 13:59:54 +0100 Subject: [PATCH 710/894] lib*/version.h: Bump Versions after release/5.0 branch This is done a second time for 5.0 because master was merged into 5.0 so that it contains the recent DOVI additions. Signed-off-by: Andreas Rheinhardt --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 4d77431842..fb1a0feec6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 18 +#define LIBAVCODEC_VERSION_MINOR 19 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index 75e3378117..05234e7f21 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 4 +#define LIBAVDEVICE_VERSION_MINOR 5 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index 1a1d7ee1cc..1a9849ef82 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 24 +#define LIBAVFILTER_VERSION_MINOR 25 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index c53d9a6444..77f4b46712 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 16 +#define LIBAVFORMAT_VERSION_MINOR 17 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index 58c617975d..5f45cf9c53 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 17 +#define LIBAVUTIL_VERSION_MINOR 18 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index 0c8db478de..e8bd6afdc8 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 3 +#define LIBPOSTPROC_VERSION_MINOR 4 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index d6fb8c3e24..61d0057cf5 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 3 +#define LIBSWRESAMPLE_VERSION_MINOR 4 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index 24448248e5..0e5583aa47 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 4 +#define LIBSWSCALE_VERSION_MINOR 5 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From 22b7c37275c611b5417722d8941844028aed7f25 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Sat, 16 Oct 2021 19:35:51 +0200 Subject: [PATCH 711/894] lavc/arm: dont assign hevc_qpel functions for non-multiple of 8 widths The assembly is written assuming that the width is a multiple of 8. However the real issue is the functions were errorneously assigned to the 2, 4, 6 & 12 widths. This behaviour never broke the decoder as samples which trigger the functions for these widths have not been found in the wild. This relies on the mappings in ff_hevc_pel_weight[]. Signed-off-by: J. Dekker --- libavcodec/arm/hevcdsp_init_neon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c index 201a088dac..112edb5edd 100644 --- a/libavcodec/arm/hevcdsp_init_neon.c +++ b/libavcodec/arm/hevcdsp_init_neon.c @@ -270,7 +270,8 @@ av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth) put_hevc_qpel_uw_neon[3][1] = ff_hevc_put_qpel_uw_h1v3_neon_8; put_hevc_qpel_uw_neon[3][2] = ff_hevc_put_qpel_uw_h2v3_neon_8; put_hevc_qpel_uw_neon[3][3] = ff_hevc_put_qpel_uw_h3v3_neon_8; - for (x = 0; x < 10; x++) { + for (x = 3; x < 10; x++) { + if (x == 4) continue; c->put_hevc_qpel[x][1][0] = ff_hevc_put_qpel_neon_wrapper; c->put_hevc_qpel[x][0][1] = ff_hevc_put_qpel_neon_wrapper; c->put_hevc_qpel[x][1][1] = ff_hevc_put_qpel_neon_wrapper; From 7fc6015de9a833868699e14880a2f3d0f187c9cc Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Sat, 16 Oct 2021 19:35:52 +0200 Subject: [PATCH 712/894] Revert "arm: hevc_qpel: Fix the assembly to work with non-multiple of 8 widths" This reverts commit 2589060b92eeeb944c6e2b50e38412c0c5fabcf4 which was originally to fix the FATE test. The real cause of the test breakage was fixed in 22b7c37275c611b5417722d8941844028aed7f25. Signed-off-by: J. Dekker --- libavcodec/arm/hevcdsp_qpel_neon.S | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/arm/hevcdsp_qpel_neon.S b/libavcodec/arm/hevcdsp_qpel_neon.S index f71bec05ed..caa6efa766 100644 --- a/libavcodec/arm/hevcdsp_qpel_neon.S +++ b/libavcodec/arm/hevcdsp_qpel_neon.S @@ -237,7 +237,7 @@ vld1.8 {d23}, [r2], r3 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #16 mov r0, r6 @@ -280,7 +280,7 @@ vld1.8 {d23}, [r2], r3 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -310,7 +310,7 @@ vld1.8 {d23}, [r2], r3 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -377,7 +377,7 @@ endfunc vst1.16 {q7}, [r0], r1 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #16 mov r0, r6 @@ -417,7 +417,7 @@ endfunc vst1.8 d0, [r0], r1 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -446,7 +446,7 @@ endfunc vst1.8 d0, [r0], r1 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 add r10, #16 @@ -533,7 +533,7 @@ endfunc \filterh q7 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #16 mov r0, r6 @@ -594,7 +594,7 @@ endfunc \filterh q7 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -641,7 +641,7 @@ endfunc \filterh q7 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 From a9214a2ca31c9d54f893c5ac4004a5ff30a08d10 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Thu, 7 Oct 2021 16:30:54 +0200 Subject: [PATCH 713/894] lavc/aarch64: add hevc sao edge 16x16 bench on AWS Graviton: hevc_sao_edge_16x16_8_c: 1857.0 hevc_sao_edge_16x16_8_neon: 211.0 hevc_sao_edge_32x32_8_c: 7802.2 hevc_sao_edge_32x32_8_neon: 808.2 hevc_sao_edge_48x48_8_c: 16764.2 hevc_sao_edge_48x48_8_neon: 1796.5 hevc_sao_edge_64x64_8_c: 32647.5 hevc_sao_edge_64x64_8_neon: 3118.5 Signed-off-by: J. Dekker --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 8 ++- libavcodec/aarch64/hevcdsp_sao_neon.S | 65 +++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index c785e46f79..747ff0412d 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -57,8 +57,8 @@ void ff_hevc_sao_band_filter_8x8_8_neon(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int16_t *sao_offset_val, int sao_left_class, int width, int height); - - +void ff_hevc_sao_edge_filter_16x16_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, + int16_t *sao_offset_val, int eo, int width, int height); av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { @@ -76,6 +76,10 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; + c->sao_edge_filter[1] = + c->sao_edge_filter[2] = + c->sao_edge_filter[3] = + c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_16x16_8_neon; } if (bit_depth == 10) { c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index f9fed8345b..4b895959d8 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -85,3 +85,68 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 bne 1b ret endfunc + +// ASSUMES STRIDE_SRC = 192 +.Lsao_edge_pos: +.word 1 // horizontal +.word 192 // vertical +.word 192 + 1 // 45 degree +.word 192 - 1 // 135 degree + +// ff_hevc_sao_edge_filter_16x16_8_neon(char *dst, char *src, ptrdiff stride_dst, +// int16 *sao_offset_val, int eo, int width, int height) +function ff_hevc_sao_edge_filter_16x16_8_neon, export=1 + adr x7, .Lsao_edge_pos + ld1 {v3.8h}, [x3] // load sao_offset_val + sxtw x5, w5 + ldr w4, [x7, w4, uxtw #2] // stride_src + mov v3.h[7], v3.h[0] // reorder to [1,2,0,3,4] + mov v3.h[0], v3.h[1] + mov v3.h[1], v3.h[2] + mov v3.h[2], v3.h[7] + // split 16bit values into two tables + uzp2 v1.16b, v3.16b, v3.16b // sao_offset_val -> upper + uzp1 v0.16b, v3.16b, v3.16b // sao_offset_val -> lower + movi v2.16b, #2 + mov x15, #192 + // strides between end of line and next src/dst + sub x15, x15, x5 // stride_src - width + sub x16, x2, x5 // stride_dst - width + mov x11, x1 // copy base src +1: // new line + mov x14, x5 // copy width + sub x12, x11, x4 // src_a (prev) = src - sao_edge_pos + add x13, x11, x4 // src_b (next) = src + sao_edge_pos +2: // process 16 bytes + ld1 {v3.16b}, [x11], #16 // load src + ld1 {v4.16b}, [x12], #16 // load src_a (prev) + ld1 {v5.16b}, [x13], #16 // load src_b (next) + cmhi v16.16b, v4.16b, v3.16b // (prev > cur) + cmhi v17.16b, v3.16b, v4.16b // (cur > prev) + cmhi v18.16b, v5.16b, v3.16b // (next > cur) + cmhi v19.16b, v3.16b, v5.16b // (cur > next) + sub v20.16b, v16.16b, v17.16b // diff0 = CMP(cur, prev) = (cur > prev) - (cur < prev) + sub v21.16b, v18.16b, v19.16b // diff1 = CMP(cur, next) = (cur > next) - (cur < next) + add v20.16b, v20.16b, v21.16b // diff = diff0 + diff1 + add v20.16b, v20.16b, v2.16b // offset_val = diff + 2 + tbl v16.16b, {v0.16b}, v20.16b + tbl v17.16b, {v1.16b}, v20.16b + uxtl v20.8h, v3.8b // src[0:7] + uxtl2 v21.8h, v3.16b // src[7:15] + zip1 v18.16b, v16.16b, v17.16b // sao_offset_val lower -> + zip2 v19.16b, v16.16b, v17.16b // sao_offset_val upper -> + sqadd v20.8h, v18.8h, v20.8h // + sao_offset_val + sqadd v21.8h, v19.8h, v21.8h + sqxtun v3.8b, v20.8h + sqxtun2 v3.16b, v21.8h + st1 {v3.16b}, [x0], #16 + subs x14, x14, #16 // filtered 16 bytes + b.ne 2b // do we have width to filter? + // no width to filter, setup next line + add x11, x11, x15 // stride src to next line + add x0, x0, x16 // stride dst to next line + subs w6, w6, #1 // filtered line + b.ne 1b // do we have lines to process? + // no lines to filter + ret +endfunc From c97ffc1a77ccaf901e642bd21ed26aaf75557745 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Thu, 7 Oct 2021 16:30:55 +0200 Subject: [PATCH 714/894] lavc/aarch64: add hevc sao edge 8x8 bench on AWS Graviton: hevc_sao_edge_8x8_8_c: 516.0 hevc_sao_edge_8x8_8_neon: 81.0 Signed-off-by: J. Dekker --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 3 ++ libavcodec/aarch64/hevcdsp_sao_neon.S | 51 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 747ff0412d..b93cec9e44 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -59,6 +59,8 @@ void ff_hevc_sao_band_filter_8x8_8_neon(uint8_t *_dst, uint8_t *_src, int width, int height); void ff_hevc_sao_edge_filter_16x16_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, int16_t *sao_offset_val, int eo, int width, int height); +void ff_hevc_sao_edge_filter_8x8_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, + int16_t *sao_offset_val, int eo, int width, int height); av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { @@ -76,6 +78,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; + c->sao_edge_filter[0] = ff_hevc_sao_edge_filter_8x8_8_neon; c->sao_edge_filter[1] = c->sao_edge_filter[2] = c->sao_edge_filter[3] = diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index 4b895959d8..167b9676d8 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -150,3 +150,54 @@ function ff_hevc_sao_edge_filter_16x16_8_neon, export=1 // no lines to filter ret endfunc + +// ff_hevc_sao_edge_filter_8x8_8_neon(char *dst, char *src, ptrdiff stride_dst, +// int16 *sao_offset_val, int eo, int width, int height) +function ff_hevc_sao_edge_filter_8x8_8_neon, export=1 + adr x7, .Lsao_edge_pos + ldr w4, [x7, w4, uxtw #2] + ld1 {v3.8h}, [x3] + mov v3.h[7], v3.h[0] + mov v3.h[0], v3.h[1] + mov v3.h[1], v3.h[2] + mov v3.h[2], v3.h[7] + uzp2 v1.16b, v3.16b, v3.16b + uzp1 v0.16b, v3.16b, v3.16b + movi v2.16b, #2 + add x16, x0, x2 + lsl x2, x2, #1 + mov x15, #192 + mov x8, x1 + sub x9, x1, x4 + add x10, x1, x4 + mov x17, #4 +1: ld1 {v3.d}[0], [ x8], x15 + ld1 {v4.d}[0], [ x9], x15 + ld1 {v5.d}[0], [x10], x15 + ld1 {v3.d}[1], [ x8], x15 + ld1 {v4.d}[1], [ x9], x15 + ld1 {v5.d}[1], [x10], x15 + cmhi v16.16b, v4.16b, v3.16b + cmhi v17.16b, v3.16b, v4.16b + cmhi v18.16b, v5.16b, v3.16b + cmhi v19.16b, v3.16b, v5.16b + sub v20.16b, v16.16b, v17.16b + sub v21.16b, v18.16b, v19.16b + add v20.16b, v20.16b, v21.16b + add v20.16b, v20.16b, v2.16b + tbl v16.16b, {v0.16b}, v20.16b + tbl v17.16b, {v1.16b}, v20.16b + uxtl v20.8h, v3.8b + uxtl2 v21.8h, v3.16b + zip1 v18.16b, v16.16b, v17.16b + zip2 v19.16b, v16.16b, v17.16b + sqadd v20.8h, v18.8h, v20.8h + sqadd v21.8h, v19.8h, v21.8h + sqxtun v6.8b, v20.8h + sqxtun v7.8b, v21.8h + st1 {v6.8b}, [ x0], x2 + st1 {v7.8b}, [x16], x2 + subs x17, x17, #1 + b.ne 1b + ret +endfunc From 89a2ed4a8b72683d0a8dfcb8c16c7a97eb740d5b Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Wed, 15 Dec 2021 20:06:20 +0100 Subject: [PATCH 715/894] lavc/aarch64: clean-up sao band 8x8 function formatting Signed-off-by: J. Dekker --- libavcodec/aarch64/hevcdsp_sao_neon.S | 65 +++++++++++---------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index 167b9676d8..73b0b3b056 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -30,24 +30,21 @@ // int width, int height) function ff_hevc_sao_band_filter_8x8_8_neon, export=1 sub sp, sp, #64 - stp xzr, xzr, [sp] - stp xzr, xzr, [sp, #16] - stp xzr, xzr, [sp, #32] - stp xzr, xzr, [sp, #48] + stp xzr, xzr, [sp] + stp xzr, xzr, [sp, #16] + stp xzr, xzr, [sp, #32] + stp xzr, xzr, [sp, #48] mov w8, #4 -0: - ldrsh x9, [x4, x8, lsl #1] // x9 = sao_offset_val[k+1] +0: ldrsh x9, [x4, x8, lsl #1] // sao_offset_val[k+1] subs w8, w8, #1 - add w10, w8, w5 // x10 = k + sao_left_class - and w10, w10, #0x1F + add w10, w8, w5 // k + sao_left_class + and w10, w10, #0x1F strh w9, [sp, x10, lsl #1] bne 0b - ld1 {v16.16b-v19.16b}, [sp], #64 - movi v20.8h, #1 -1: // beginning of line - mov w8, w6 -2: - // Simple layout for accessing 16bit values + ld1 {v16.16b-v19.16b}, [sp], #64 + movi v20.8h, #1 +1: mov w8, w6 // beginning of line +2: // Simple layout for accessing 16bit values // with 8bit LUT. // // 00 01 02 03 04 05 06 07 @@ -55,33 +52,21 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 // |xDE#xAD|xCA#xFE|xBE#xEF|xFE#xED|.... // +-----------------------------------> // i-0 i-1 i-2 i-3 - // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); - ld1 {v2.8b}, [x1] - // load src[x] - uxtl v0.8h, v2.8b - // >> shift - ushr v2.8h, v0.8h, #3 // BIT_DEPTH - 3 - // x2 (access lower short) - shl v1.8h, v2.8h, #1 // low (x2, accessing short) - // +1 access upper short - add v3.8h, v1.8h, v20.8h - // shift insert index to upper byte - sli v1.8h, v3.8h, #8 - // table - tbx v2.16b, {v16.16b-v19.16b}, v1.16b - // src[x] + table - add v1.8h, v0.8h, v2.8h - // clip + narrow - sqxtun v4.8b, v1.8h - // store - st1 {v4.8b}, [x0] - // done 8 pixels - subs w8, w8, #8 + ld1 {v2.8b}, [x1] // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); + uxtl v0.8h, v2.8b // load src[x] + ushr v2.8h, v0.8h, #3 // >> BIT_DEPTH - 3 + shl v1.8h, v2.8h, #1 // low (x2, accessing short) + add v3.8h, v1.8h, v20.8h // +1 access upper short + sli v1.8h, v3.8h, #8 // shift insert index to upper byte + tbx v2.16b, {v16.16b-v19.16b}, v1.16b // table + add v1.8h, v0.8h, v2.8h // src[x] + table + sqxtun v4.8b, v1.8h // clip + narrow + st1 {v4.8b}, [x0] // store + subs w8, w8, #8 // done 8 pixels bne 2b - // finished line - subs w7, w7, #1 - add x0, x0, x2 // dst += stride_dst - add x1, x1, x3 // src += stride_src + subs w7, w7, #1 // finished line, prep. new + add x0, x0, x2 // dst += stride_dst + add x1, x1, x3 // src += stride_src bne 1b ret endfunc From f63f9be37c799ddc835af358034630d31fb7db02 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Wed, 17 Nov 2021 05:56:13 +0100 Subject: [PATCH 716/894] lavc/aarch64: add hevc sao band 8x8 tiling bench on AWS Graviton: hevc_sao_band_8x8_8_c: 317.5 hevc_sao_band_8x8_8_neon: 97.5 hevc_sao_band_16x16_8_c: 1115.0 hevc_sao_band_16x16_8_neon: 322.7 hevc_sao_band_32x32_8_c: 4599.2 hevc_sao_band_32x32_8_neon: 1246.2 hevc_sao_band_48x48_8_c: 10021.7 hevc_sao_band_48x48_8_neon: 2740.5 hevc_sao_band_64x64_8_c: 17635.0 hevc_sao_band_64x64_8_neon: 4875.7 Signed-off-by: J. Dekker --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 6 +++++- libavcodec/aarch64/hevcdsp_sao_neon.S | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index b93cec9e44..2002530266 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -77,7 +77,11 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; - c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; + c->sao_band_filter[0] = + c->sao_band_filter[1] = + c->sao_band_filter[2] = + c->sao_band_filter[3] = + c->sao_band_filter[4] = ff_hevc_sao_band_filter_8x8_8_neon; c->sao_edge_filter[0] = ff_hevc_sao_edge_filter_8x8_8_neon; c->sao_edge_filter[1] = c->sao_edge_filter[2] = diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index 73b0b3b056..d524323fe8 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -3,7 +3,7 @@ * * AArch64 NEON optimised SAO functions for HEVC decoding * - * Copyright (c) 2020 Josh Dekker + * Copyright (c) 2020-2021 J. Dekker * * This file is part of FFmpeg. * @@ -35,6 +35,7 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 stp xzr, xzr, [sp, #32] stp xzr, xzr, [sp, #48] mov w8, #4 + sxtw x6, w6 0: ldrsh x9, [x4, x8, lsl #1] // sao_offset_val[k+1] subs w8, w8, #1 add w10, w8, w5 // k + sao_left_class @@ -43,7 +44,9 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 bne 0b ld1 {v16.16b-v19.16b}, [sp], #64 movi v20.8h, #1 -1: mov w8, w6 // beginning of line + sub x2, x2, x6 // stride_dst - width + sub x3, x3, x6 // stride_src - width +1: mov x8, x6 // beginning of line 2: // Simple layout for accessing 16bit values // with 8bit LUT. // @@ -52,7 +55,7 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 // |xDE#xAD|xCA#xFE|xBE#xEF|xFE#xED|.... // +-----------------------------------> // i-0 i-1 i-2 i-3 - ld1 {v2.8b}, [x1] // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); + ld1 {v2.8b}, [x1], #8 // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); uxtl v0.8h, v2.8b // load src[x] ushr v2.8h, v0.8h, #3 // >> BIT_DEPTH - 3 shl v1.8h, v2.8h, #1 // low (x2, accessing short) @@ -61,7 +64,7 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 tbx v2.16b, {v16.16b-v19.16b}, v1.16b // table add v1.8h, v0.8h, v2.8h // src[x] + table sqxtun v4.8b, v1.8h // clip + narrow - st1 {v4.8b}, [x0] // store + st1 {v4.8b}, [x0], #8 // store subs w8, w8, #8 // done 8 pixels bne 2b subs w7, w7, #1 // finished line, prep. new From 10e4b2b1d243435445ff537cc9e3948b7490eb5b Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 4 Jan 2022 14:34:36 +0100 Subject: [PATCH 717/894] lavfi/showinfo: fix printf precision for dovi metadata Fix warning caused by this field changing from uint64_t to uint16_t. Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_showinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 909ad4f8d7..71728bced4 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -499,7 +499,7 @@ static void dump_dovi_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) av_log(ctx, AV_LOG_INFO, "} "); } - av_log(ctx, AV_LOG_INFO, "}; nlq_offset=%"PRIu64"; ", nlq->nlq_offset); + av_log(ctx, AV_LOG_INFO, "}; nlq_offset=%"PRIu16"; ", nlq->nlq_offset); av_log(ctx, AV_LOG_INFO, "vdr_in_max=%"PRIu64"; ", nlq->vdr_in_max); switch (mapping->nlq_method_idc) { case AV_DOVI_NLQ_LINEAR_DZ: From 5d58355bf1a7bd07b0f08bf1f90f4aba8b89d727 Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Wed, 29 Dec 2021 18:18:20 +0800 Subject: [PATCH 718/894] avcodec: [loongarch] Optimize hpeldsp with LASX. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./ffmpeg -i 8_mpeg4_1080p_24fps_12Mbps.avi -f rawvideo -y /dev/null -an before:376fps after :433fps Reviewed-by: 殷时友 Signed-off-by: Michael Niedermayer --- libavcodec/hpeldsp.c | 2 + libavcodec/hpeldsp.h | 1 + libavcodec/loongarch/Makefile | 2 + libavcodec/loongarch/hpeldsp_init_loongarch.c | 50 + libavcodec/loongarch/hpeldsp_lasx.c | 1287 +++++++++++++++++ libavcodec/loongarch/hpeldsp_lasx.h | 58 + 6 files changed, 1400 insertions(+) create mode 100644 libavcodec/loongarch/hpeldsp_init_loongarch.c create mode 100644 libavcodec/loongarch/hpeldsp_lasx.c create mode 100644 libavcodec/loongarch/hpeldsp_lasx.h diff --git a/libavcodec/hpeldsp.c b/libavcodec/hpeldsp.c index 8e2fd8fcf5..843ba399c5 100644 --- a/libavcodec/hpeldsp.c +++ b/libavcodec/hpeldsp.c @@ -367,4 +367,6 @@ av_cold void ff_hpeldsp_init(HpelDSPContext *c, int flags) ff_hpeldsp_init_x86(c, flags); if (ARCH_MIPS) ff_hpeldsp_init_mips(c, flags); + if (ARCH_LOONGARCH64) + ff_hpeldsp_init_loongarch(c, flags); } diff --git a/libavcodec/hpeldsp.h b/libavcodec/hpeldsp.h index 768139bfc9..45e81b10a5 100644 --- a/libavcodec/hpeldsp.h +++ b/libavcodec/hpeldsp.h @@ -102,5 +102,6 @@ void ff_hpeldsp_init_arm(HpelDSPContext *c, int flags); void ff_hpeldsp_init_ppc(HpelDSPContext *c, int flags); void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags); void ff_hpeldsp_init_mips(HpelDSPContext *c, int flags); +void ff_hpeldsp_init_loongarch(HpelDSPContext *c, int flags); #endif /* AVCODEC_HPELDSP_H */ diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index baf5f92e84..07a401d883 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -5,6 +5,7 @@ OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o OBJS-$(CONFIG_VC1DSP) += loongarch/vc1dsp_init_loongarch.o +OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ @@ -12,6 +13,7 @@ LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ loongarch/h264_deblock_lasx.o LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o LASX-OBJS-$(CONFIG_VC1_DECODER) += loongarch/vc1dsp_lasx.o +LASX-OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_lasx.o LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ loongarch/vp8_lpf_lsx.o LSX-OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9_mc_lsx.o \ diff --git a/libavcodec/loongarch/hpeldsp_init_loongarch.c b/libavcodec/loongarch/hpeldsp_init_loongarch.c new file mode 100644 index 0000000000..1690be5438 --- /dev/null +++ b/libavcodec/loongarch/hpeldsp_init_loongarch.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/hpeldsp.h" +#include "libavcodec/loongarch/hpeldsp_lasx.h" + +void ff_hpeldsp_init_loongarch(HpelDSPContext *c, int flags) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + c->put_pixels_tab[0][0] = ff_put_pixels16_8_lsx; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_8_lasx; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_8_lasx; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_8_lasx; + + c->put_pixels_tab[1][0] = ff_put_pixels8_8_lasx; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_8_lasx; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_8_lasx; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_8_lasx; + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_8_lsx; + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_8_lasx; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_8_lasx; + c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_8_lasx; + + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_8_lasx; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_8_lasx; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_8_lasx; + c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_8_lasx; + } +} diff --git a/libavcodec/loongarch/hpeldsp_lasx.c b/libavcodec/loongarch/hpeldsp_lasx.c new file mode 100644 index 0000000000..dd2ae173da --- /dev/null +++ b/libavcodec/loongarch/hpeldsp_lasx.c @@ -0,0 +1,1287 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "hpeldsp_lasx.h" + +static av_always_inline void +put_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, + int dst_stride, int src_stride1, int src_stride2, int h) +{ + int stride1_2, stride1_3, stride1_4; + int stride2_2, stride2_3, stride2_4; + __asm__ volatile ( + "slli.d %[stride1_2], %[srcStride1], 1 \n\t" + "slli.d %[stride2_2], %[srcStride2], 1 \n\t" + "add.d %[stride1_3], %[stride1_2], %[srcStride1] \n\t" + "add.d %[stride2_3], %[stride2_2], %[srcStride2] \n\t" + "slli.d %[stride1_4], %[stride1_2], 1 \n\t" + "slli.d %[stride2_4], %[stride2_2], 1 \n\t" + "1: \n\t" + "vld $vr0, %[src1], 0 \n\t" + "vldx $vr1, %[src1], %[srcStride1] \n\t" + "vldx $vr2, %[src1], %[stride1_2] \n\t" + "vldx $vr3, %[src1], %[stride1_3] \n\t" + "add.d %[src1], %[src1], %[stride1_4] \n\t" + + "vld $vr4, %[src2], 0 \n\t" + "vldx $vr5, %[src2], %[srcStride2] \n\t" + "vldx $vr6, %[src2], %[stride2_2] \n\t" + "vldx $vr7, %[src2], %[stride2_3] \n\t" + "add.d %[src2], %[src2], %[stride2_4] \n\t" + + "addi.d %[h], %[h], -4 \n\t" + + "vavgr.bu $vr0, $vr4, $vr0 \n\t" + "vavgr.bu $vr1, $vr5, $vr1 \n\t" + "vavgr.bu $vr2, $vr6, $vr2 \n\t" + "vavgr.bu $vr3, $vr7, $vr3 \n\t" + "vstelm.d $vr0, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr1, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr2, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr3, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "bnez %[h], 1b \n\t" + + : [dst]"+&r"(dst), [src2]"+&r"(src2), [src1]"+&r"(src1), + [h]"+&r"(h), [stride1_2]"=&r"(stride1_2), + [stride1_3]"=&r"(stride1_3), [stride1_4]"=&r"(stride1_4), + [stride2_2]"=&r"(stride2_2), [stride2_3]"=&r"(stride2_3), + [stride2_4]"=&r"(stride2_4) + : [dstStride]"r"(dst_stride), [srcStride1]"r"(src_stride1), + [srcStride2]"r"(src_stride2) + : "memory" + ); +} + +static av_always_inline void +put_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, + int dst_stride, int src_stride1, int src_stride2, int h) +{ + int stride1_2, stride1_3, stride1_4; + int stride2_2, stride2_3, stride2_4; + int dststride2, dststride3, dststride4; + __asm__ volatile ( + "slli.d %[stride1_2], %[srcStride1], 1 \n\t" + "slli.d %[stride2_2], %[srcStride2], 1 \n\t" + "slli.d %[dststride2], %[dstStride], 1 \n\t" + "add.d %[stride1_3], %[stride1_2], %[srcStride1] \n\t" + "add.d %[stride2_3], %[stride2_2], %[srcStride2] \n\t" + "add.d %[dststride3], %[dststride2], %[dstStride] \n\t" + "slli.d %[stride1_4], %[stride1_2], 1 \n\t" + "slli.d %[stride2_4], %[stride2_2], 1 \n\t" + "slli.d %[dststride4], %[dststride2], 1 \n\t" + "1: \n\t" + "vld $vr0, %[src1], 0 \n\t" + "vldx $vr1, %[src1], %[srcStride1] \n\t" + "vldx $vr2, %[src1], %[stride1_2] \n\t" + "vldx $vr3, %[src1], %[stride1_3] \n\t" + "add.d %[src1], %[src1], %[stride1_4] \n\t" + + "vld $vr4, %[src2], 0 \n\t" + "vldx $vr5, %[src2], %[srcStride2] \n\t" + "vldx $vr6, %[src2], %[stride2_2] \n\t" + "vldx $vr7, %[src2], %[stride2_3] \n\t" + "add.d %[src2], %[src2], %[stride2_4] \n\t" + + "addi.d %[h], %[h], -4 \n\t" + + "vavgr.bu $vr0, $vr4, $vr0 \n\t" + "vavgr.bu $vr1, $vr5, $vr1 \n\t" + "vavgr.bu $vr2, $vr6, $vr2 \n\t" + "vavgr.bu $vr3, $vr7, $vr3 \n\t" + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dststride2] \n\t" + "vstx $vr3, %[dst], %[dststride3] \n\t" + "add.d %[dst], %[dst], %[dststride4] \n\t" + "bnez %[h], 1b \n\t" + + : [dst]"+&r"(dst), [src2]"+&r"(src2), [src1]"+&r"(src1), + [h]"+&r"(h), [stride1_2]"=&r"(stride1_2), + [stride1_3]"=&r"(stride1_3), [stride1_4]"=&r"(stride1_4), + [stride2_2]"=&r"(stride2_2), [stride2_3]"=&r"(stride2_3), + [stride2_4]"=&r"(stride2_4), [dststride2]"=&r"(dststride2), + [dststride3]"=&r"(dststride3), [dststride4]"=&r"(dststride4) + : [dstStride]"r"(dst_stride), [srcStride1]"r"(src_stride1), + [srcStride2]"r"(src_stride2) + : "memory" + ); +} + +void ff_put_pixels8_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + uint64_t tmp[8]; + int h_8 = h >> 3; + int res = h & 7; + ptrdiff_t stride2, stride3, stride4; + + __asm__ volatile ( + "beqz %[h_8], 2f \n\t" + "slli.d %[stride2], %[stride], 1 \n\t" + "add.d %[stride3], %[stride2], %[stride] \n\t" + "slli.d %[stride4], %[stride2], 1 \n\t" + "1: \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride2] \n\t" + "ldx.d %[tmp3], %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + "ld.d %[tmp4], %[src], 0x0 \n\t" + "ldx.d %[tmp5], %[src], %[stride] \n\t" + "ldx.d %[tmp6], %[src], %[stride2] \n\t" + "ldx.d %[tmp7], %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + + "addi.d %[h_8], %[h_8], -1 \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride2] \n\t" + "stx.d %[tmp3], %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "st.d %[tmp4], %[dst], 0x0 \n\t" + "stx.d %[tmp5], %[dst], %[stride] \n\t" + "stx.d %[tmp6], %[dst], %[stride2] \n\t" + "stx.d %[tmp7], %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "bnez %[h_8], 1b \n\t" + + "2: \n\t" + "beqz %[res], 4f \n\t" + "3: \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "add.d %[src], %[src], %[stride] \n\t" + "addi.d %[res], %[res], -1 \n\t" + "st.d %[tmp0], %[dst], 0x0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "bnez %[res], 3b \n\t" + "4: \n\t" + : [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]), + [tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]), + [tmp4]"=&r"(tmp[4]), [tmp5]"=&r"(tmp[5]), + [tmp6]"=&r"(tmp[6]), [tmp7]"=&r"(tmp[7]), + [dst]"+&r"(block), [src]"+&r"(pixels), + [h_8]"+&r"(h_8), [res]"+&r"(res), + [stride2]"=&r"(stride2), [stride3]"=&r"(stride3), + [stride4]"=&r"(stride4) + : [stride]"r"(line_size) + : "memory" + ); +} + +void ff_put_pixels16_8_lsx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + int h_8 = h >> 3; + int res = h & 7; + ptrdiff_t stride2, stride3, stride4; + + __asm__ volatile ( + "beqz %[h_8], 2f \n\t" + "slli.d %[stride2], %[stride], 1 \n\t" + "add.d %[stride3], %[stride2], %[stride] \n\t" + "slli.d %[stride4], %[stride2], 1 \n\t" + "1: \n\t" + "vld $vr0, %[src], 0x0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride2] \n\t" + "vldx $vr3, %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + "vld $vr4, %[src], 0x0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride2] \n\t" + "vldx $vr7, %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + + "addi.d %[h_8], %[h_8], -1 \n\t" + + "vst $vr0, %[dst], 0x0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride2] \n\t" + "vstx $vr3, %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "vst $vr4, %[dst], 0x0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride2] \n\t" + "vstx $vr7, %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "bnez %[h_8], 1b \n\t" + + "2: \n\t" + "beqz %[res], 4f \n\t" + "3: \n\t" + "vld $vr0, %[src], 0x0 \n\t" + "add.d %[src], %[src], %[stride] \n\t" + "addi.d %[res], %[res], -1 \n\t" + "vst $vr0, %[dst], 0x0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "bnez %[res], 3b \n\t" + "4: \n\t" + : [dst]"+&r"(block), [src]"+&r"(pixels), + [h_8]"+&r"(h_8), [res]"+&r"(res), + [stride2]"=&r"(stride2), [stride3]"=&r"(stride3), + [stride4]"=&r"(stride4) + : [stride]"r"(line_size) + : "memory" + ); +} + +void ff_put_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels8_l2_8_lsx(block, pixels, pixels + 1, line_size, line_size, + line_size, h); +} + +void ff_put_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels8_l2_8_lsx(block, pixels, pixels + line_size, line_size, + line_size, line_size, h); +} + +void ff_put_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels16_l2_8_lsx(block, pixels, pixels + 1, line_size, line_size, + line_size, h); +} + +void ff_put_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels16_l2_8_lsx(block, pixels, pixels + line_size, line_size, + line_size, line_size, h); +} + +static void common_hz_bil_no_rnd_16x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x -1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, + src4, 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); +} + +static void common_hz_bil_no_rnd_8x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); +} + +void ff_put_no_rnd_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 16) { + common_hz_bil_no_rnd_16x16_lasx(pixels, line_size, block, line_size); + } else if (h == 8) { + common_hz_bil_no_rnd_8x16_lasx(pixels, line_size, block, line_size); + } +} + +static void common_vt_bil_no_rnd_16x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i src9, src10, src11, src12, src13, src14, src15, src16; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src8 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src9, src10); + src11 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src12 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src13, src14); + src15 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src16 = __lasx_xvld(_src, 0); + + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, + 0x20, src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src9, src8, 0x20, src10, src9, 0x20, src11, + src10, 0x20, src12, src11, 0x20, src8, src9, src10, src11); + DUP4_ARG3(__lasx_xvpermi_q, src13, src12, 0x20, src14, src13, 0x20, src15, + src14, 0x20, src16, src15, 0x20, src12, src13, src14, src15); + DUP4_ARG2(__lasx_xvavg_bu, src0, src1, src2, src3, src4, src5, src6, src7, + src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvavg_bu, src8, src9, src10, src11, src12, src13, src14, + src15, src8, src10, src12, src14); + + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 0); + __lasx_xvstelm_d(src2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 2); + __lasx_xvstelm_d(src2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 0); + __lasx_xvstelm_d(src4, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 2); + __lasx_xvstelm_d(src4, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 0); + __lasx_xvstelm_d(src6, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 2); + __lasx_xvstelm_d(src6, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src8, dst, 0, 0); + __lasx_xvstelm_d(src8, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src8, dst, 0, 2); + __lasx_xvstelm_d(src8, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src10, dst, 0, 0); + __lasx_xvstelm_d(src10, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src10, dst, 0, 2); + __lasx_xvstelm_d(src10, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src12, dst, 0, 0); + __lasx_xvstelm_d(src12, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src12, dst, 0, 2); + __lasx_xvstelm_d(src12, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src14, dst, 0, 0); + __lasx_xvstelm_d(src14, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src14, dst, 0, 2); + __lasx_xvstelm_d(src14, dst, 8, 3); +} + +static void common_vt_bil_no_rnd_8x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src8 = __lasx_xvld(_src, 0); + + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, + 0x20, src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvavg_bu, src0, src1, src2, src3, src4, src5, src6, src7, + src0, src2, src4, src6); + + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 0); + __lasx_xvstelm_d(src2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 2); + __lasx_xvstelm_d(src2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 0); + __lasx_xvstelm_d(src4, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 2); + __lasx_xvstelm_d(src4, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 0); + __lasx_xvstelm_d(src6, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 2); + __lasx_xvstelm_d(src6, dst, 8, 3); +} + +void ff_put_no_rnd_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 16) { + common_vt_bil_no_rnd_16x16_lasx(pixels, line_size, block, line_size); + } else if (h == 8) { + common_vt_bil_no_rnd_8x16_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hv_bil_no_rnd_16x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + __m256i src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, + src6, 0x02, src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, + src14, 0x02, src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, + src8, src9); + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, src5, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, src9, + sum4, sum5, sum6, sum7); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum4, 1, sum5, 1, sum6, 1, sum7, 1, + sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, sum4, 2, + sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, src6, 0x02, + src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, src14, 0x02, + src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, src8, src9); + + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, src5, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, src9, + sum4, sum5, sum6, sum7); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum4, 1, sum5, 1, sum6, 1, sum7, 1, + sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, sum4, 2, + sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); +} + +static void common_hv_bil_no_rnd_8x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + __m256i src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, + src6, 0x02, src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, + src14, 0x02, src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, src8, src9); + + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, src5, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, src9, + sum4, sum5, sum6, sum7); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum4, 1, sum5, 1, sum6, 1, sum7, 1, + sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, sum4, 2, + sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); +} + +void ff_put_no_rnd_pixels16_xy2_8_lasx(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 16) { + common_hv_bil_no_rnd_16x16_lasx(pixels, line_size, block, line_size); + } else if (h == 8) { + common_hv_bil_no_rnd_8x16_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hz_bil_no_rnd_8x8_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, src10, src11, src12, src13, src14, src15; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src8 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src9, src10); + src11 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src12 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src13, src14); + src15 = __lasx_xvldx(_src, src_stride_3x); + + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src3, src2, src5, src4, src7, + src6, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvpickev_d, src9, src8, src11, src10, src13, src12, src15, + src14, src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src1, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src1, dst + dst_stride_3x, 0, 3); +} + +static void common_hz_bil_no_rnd_4x8_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + uint8_t *_src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src1); + src0 = __lasx_xvavg_bu(src0, src1); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); +} + +void ff_put_no_rnd_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 8) { + common_hz_bil_no_rnd_8x8_lasx(pixels, line_size, block, line_size); + } else if (h == 4) { + common_hz_bil_no_rnd_4x8_lasx(pixels, line_size, block, line_size); + } +} + +static void common_vt_bil_no_rnd_8x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src8 = __lasx_xvld(_src, 0); + + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src2, src1, src3, src2, src4, src3, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvpickev_d, src5, src4, src6, src5, src7, src6, src8, src7, + src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src2, src0, 0x20, src3, src1, 0x20, src6, src4, + 0x20, src7, src5, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src1); + src1 = __lasx_xvavg_bu(src2, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src1, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src1, dst + dst_stride_3x, 0, 3); +} + +static void common_vt_bil_no_rnd_4x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP4_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, _src, + src_stride_3x, _src, src_stride_4x, src1, src2, src3, src4); + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src2, src1, src3, src2, src4, src3, + src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src2, src0, 0x20, src3, src1, 0x20, src0, src1); + src0 = __lasx_xvavg_bu(src0, src1); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); +} + +void ff_put_no_rnd_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 8) { + common_vt_bil_no_rnd_8x8_lasx(pixels, line_size, block, line_size); + } else if (h == 4) { + common_vt_bil_no_rnd_4x8_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hv_bil_no_rnd_8x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG2(__lasx_xvilvl_b, src9, src0, src10, src1, src11, src2, src12, src3, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvilvl_b, src13, src4, src14, src5, src15, src6, src16, src7, + src4, src5, src6, src7); + src8 = __lasx_xvilvl_b(src17, src8); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, + 0x20, src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src0, src0, src1, src1, src2, src2, + src3, src3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src4, src4, src5, src5, src6, src6, + src7, src7, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvadd_h, src0, src1, src2, src3, src4, src5, src6, src7, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP2_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum0, sum1); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum1, dst + dst_stride_3x, 0, 3); +} + +static void common_hv_bil_no_rnd_4x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, sum0, sum1; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src5 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src6, src7); + src8 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src4, src9); + + DUP4_ARG2(__lasx_xvilvl_b, src5, src0, src6, src1, src7, src2, src8, src3, + src0, src1, src2, src3); + src4 = __lasx_xvilvl_b(src9, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src0, src0, src1, src1, src2, src2, + src3, src3, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvadd_h, src0, src1, src2, src3, sum0, sum1); + sum0 = __lasx_xvaddi_hu(sum0, 1); + sum1 = __lasx_xvaddi_hu(sum1, 1); + sum0 = __lasx_xvsrani_b_h(sum1, sum0, 2); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum0, dst + dst_stride_3x, 0, 3); +} + +void ff_put_no_rnd_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 8) { + common_hv_bil_no_rnd_8x8_lasx(pixels, line_size, block, line_size); + } else if (h == 4) { + common_hv_bil_no_rnd_4x8_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hv_bil_16w_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + uint8_t height) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + __m256i src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; + uint8_t loop_cnt; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, + src6, 0x02, src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, + src14, 0x02, src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, + src8, src9); + + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, + src3, sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, + src3, sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, + src5, sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, + src9, sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrarni_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, + sum4, 2, sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); + dst += dst_stride; + } +} + +void ff_put_pixels16_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + common_hv_bil_16w_lasx(pixels, line_size, block, line_size, h); +} + +static void common_hv_bil_8w_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + uint8_t height) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, sum0, sum1; + uint8_t loop_cnt; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src0, src5); + _src += src_stride; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src1 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src2, src3); + src4 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src6 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src7, src8); + src9 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG2(__lasx_xvilvl_b, src5, src0, src6, src1, src7, src2, src8, src3, + src0, src1, src2, src3); + src5 = __lasx_xvilvl_b(src9, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src5, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src0, src0, src1, src1, src2, src2, + src3, src3, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvadd_h, src0, src1, src2, src3, sum0, sum1); + sum0 = __lasx_xvsrarni_b_h(sum1, sum0, 2); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + src0 = src4; + src5 = src9; + } +} + +void ff_put_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + common_hv_bil_8w_lasx(pixels, line_size, block, line_size, h); +} diff --git a/libavcodec/loongarch/hpeldsp_lasx.h b/libavcodec/loongarch/hpeldsp_lasx.h new file mode 100644 index 0000000000..2e035eade8 --- /dev/null +++ b/libavcodec/loongarch/hpeldsp_lasx.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_HPELDSP_LASX_H +#define AVCODEC_LOONGARCH_HPELDSP_LASX_H + +#include +#include +#include "libavutil/attributes.h" + +void ff_put_pixels8_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_pixels16_8_lsx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_no_rnd_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels16_xy2_8_lasx(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +#endif From 555b850bd56c87007c6b7b02dbb1e474e9911dfa Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Wed, 29 Dec 2021 18:18:21 +0800 Subject: [PATCH 719/894] avcodec: [loongarch] Optimize idctdstp with LASX. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./ffmpeg -i 8_mpeg4_1080p_24fps_12Mbps.avi -f rawvideo -y /dev/null -an before:433fps after :552fps Reviewed-by: 殷时友 Signed-off-by: Michael Niedermayer --- libavcodec/idctdsp.c | 2 + libavcodec/idctdsp.h | 2 + libavcodec/loongarch/Makefile | 3 + libavcodec/loongarch/idctdsp_init_loongarch.c | 45 +++ libavcodec/loongarch/idctdsp_lasx.c | 124 ++++++++ libavcodec/loongarch/idctdsp_loongarch.h | 41 +++ libavcodec/loongarch/simple_idct_lasx.c | 297 ++++++++++++++++++ 7 files changed, 514 insertions(+) create mode 100644 libavcodec/loongarch/idctdsp_init_loongarch.c create mode 100644 libavcodec/loongarch/idctdsp_lasx.c create mode 100644 libavcodec/loongarch/idctdsp_loongarch.h create mode 100644 libavcodec/loongarch/simple_idct_lasx.c diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 846ed0b0f8..71bd03c606 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -315,6 +315,8 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) ff_idctdsp_init_x86(c, avctx, high_bit_depth); if (ARCH_MIPS) ff_idctdsp_init_mips(c, avctx, high_bit_depth); + if (ARCH_LOONGARCH) + ff_idctdsp_init_loongarch(c, avctx, high_bit_depth); ff_init_scantable_permutation(c->idct_permutation, c->perm_type); diff --git a/libavcodec/idctdsp.h b/libavcodec/idctdsp.h index ca21a31a02..014488aec3 100644 --- a/libavcodec/idctdsp.h +++ b/libavcodec/idctdsp.h @@ -118,5 +118,7 @@ void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth); void ff_idctdsp_init_mips(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth); +void ff_idctdsp_init_loongarch(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); #endif /* AVCODEC_IDCTDSP_H */ diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 07a401d883..c4d71e801b 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -6,6 +6,7 @@ OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o OBJS-$(CONFIG_VC1DSP) += loongarch/vc1dsp_init_loongarch.o OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_init_loongarch.o +OBJS-$(CONFIG_IDCTDSP) += loongarch/idctdsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ @@ -14,6 +15,8 @@ LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o LASX-OBJS-$(CONFIG_VC1_DECODER) += loongarch/vc1dsp_lasx.o LASX-OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_lasx.o +LASX-OBJS-$(CONFIG_IDCTDSP) += loongarch/simple_idct_lasx.o \ + loongarch/idctdsp_lasx.o LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ loongarch/vp8_lpf_lsx.o LSX-OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9_mc_lsx.o \ diff --git a/libavcodec/loongarch/idctdsp_init_loongarch.c b/libavcodec/loongarch/idctdsp_init_loongarch.c new file mode 100644 index 0000000000..9d1d21cc18 --- /dev/null +++ b/libavcodec/loongarch/idctdsp_init_loongarch.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/cpu.h" +#include "idctdsp_loongarch.h" +#include "libavcodec/xvididct.h" + +av_cold void ff_idctdsp_init_loongarch(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + if ((avctx->lowres != 1) && (avctx->lowres != 2) && (avctx->lowres != 3) && + (avctx->bits_per_raw_sample != 10) && + (avctx->bits_per_raw_sample != 12) && + (avctx->idct_algo == FF_IDCT_AUTO)) { + c->idct_put = ff_simple_idct_put_lasx; + c->idct_add = ff_simple_idct_add_lasx; + c->idct = ff_simple_idct_lasx; + c->perm_type = FF_IDCT_PERM_NONE; + } + c->put_pixels_clamped = ff_put_pixels_clamped_lasx; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_lasx; + c->add_pixels_clamped = ff_add_pixels_clamped_lasx; + } +} diff --git a/libavcodec/loongarch/idctdsp_lasx.c b/libavcodec/loongarch/idctdsp_lasx.c new file mode 100644 index 0000000000..1cfab0e028 --- /dev/null +++ b/libavcodec/loongarch/idctdsp_lasx.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "idctdsp_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +void ff_put_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t stride) +{ + __m256i b0, b1, b2, b3; + __m256i temp0, temp1; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + b0, b1, b2, b3); + DUP4_ARG1(__lasx_xvclip255_h, b0, b1, b2, b3, b0, b1, b2, b3); + DUP2_ARG2(__lasx_xvpickev_b, b1, b0, b3, b2, temp0, temp1); + __lasx_xvstelm_d(temp0, pixels, 0, 0); + __lasx_xvstelm_d(temp0, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp0, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp0, pixels + stride_3x, 0, 3); + pixels += stride_4x; + __lasx_xvstelm_d(temp1, pixels, 0, 0); + __lasx_xvstelm_d(temp1, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp1, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp1, pixels + stride_3x, 0, 3); +} + +void ff_put_signed_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t stride) +{ + __m256i b0, b1, b2, b3; + __m256i temp0, temp1; + __m256i const_128 = {0x0080008000800080, 0x0080008000800080, + 0x0080008000800080, 0x0080008000800080}; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + b0, b1, b2, b3); + DUP4_ARG2(__lasx_xvadd_h, b0, const_128, b1, const_128, b2, const_128, + b3, const_128, b0, b1, b2, b3); + DUP4_ARG1(__lasx_xvclip255_h, b0, b1, b2, b3, b0, b1, b2, b3); + DUP2_ARG2(__lasx_xvpickev_b, b1, b0, b3, b2, temp0, temp1); + __lasx_xvstelm_d(temp0, pixels, 0, 0); + __lasx_xvstelm_d(temp0, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp0, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp0, pixels + stride_3x, 0, 3); + pixels += stride_4x; + __lasx_xvstelm_d(temp1, pixels, 0, 0); + __lasx_xvstelm_d(temp1, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp1, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp1, pixels + stride_3x, 0, 3); +} + +void ff_add_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t stride) +{ + __m256i b0, b1, b2, b3; + __m256i p0, p1, p2, p3, p4, p5, p6, p7; + __m256i temp0, temp1, temp2, temp3; + uint8_t *pix = pixels; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + b0, b1, b2, b3); + p0 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p1 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p2 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p3 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p4 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p5 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p6 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p7 = __lasx_xvldrepl_d(pix, 0); + DUP4_ARG3(__lasx_xvpermi_q, p1, p0, 0x20, p3, p2, 0x20, p5, p4, 0x20, + p7, p6, 0x20, temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvaddw_h_h_bu, b0, temp0, b1, temp1, b2, temp2, b3, temp3, + temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_xvclip255_h, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvpickev_b, temp1, temp0, temp3, temp2, temp0, temp1); + __lasx_xvstelm_d(temp0, pixels, 0, 0); + __lasx_xvstelm_d(temp0, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp0, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp0, pixels + stride_3x, 0, 3); + pixels += stride_4x; + __lasx_xvstelm_d(temp1, pixels, 0, 0); + __lasx_xvstelm_d(temp1, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp1, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp1, pixels + stride_3x, 0, 3); +} diff --git a/libavcodec/loongarch/idctdsp_loongarch.h b/libavcodec/loongarch/idctdsp_loongarch.h new file mode 100644 index 0000000000..cae8e7af58 --- /dev/null +++ b/libavcodec/loongarch/idctdsp_loongarch.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LOONGARCH_IDCTDSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_IDCTDSP_LOONGARCH_H + +#include +#include "libavcodec/mpegvideo.h" + +void ff_simple_idct_lasx(int16_t *block); +void ff_simple_idct_put_lasx(uint8_t *dest, ptrdiff_t stride_dst, int16_t *block); +void ff_simple_idct_add_lasx(uint8_t *dest, ptrdiff_t stride_dst, int16_t *block); +void ff_put_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t line_size); +void ff_put_signed_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t line_size); +void ff_add_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t line_size); + +#endif /* AVCODEC_LOONGARCH_IDCTDSP_LOONGARCH_H */ diff --git a/libavcodec/loongarch/simple_idct_lasx.c b/libavcodec/loongarch/simple_idct_lasx.c new file mode 100644 index 0000000000..a0d936b666 --- /dev/null +++ b/libavcodec/loongarch/simple_idct_lasx.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "idctdsp_loongarch.h" + +#define LASX_TRANSPOSE4x16(in_0, in_1, in_2, in_3, out_0, out_1, out_2, out_3) \ +{ \ + __m256i temp_0, temp_1, temp_2, temp_3; \ + __m256i temp_4, temp_5, temp_6, temp_7; \ + DUP4_ARG3(__lasx_xvpermi_q, in_2, in_0, 0x20, in_2, in_0, 0x31, in_3, in_1,\ + 0x20, in_3, in_1, 0x31, temp_0, temp_1, temp_2, temp_3); \ + DUP2_ARG2(__lasx_xvilvl_h, temp_1, temp_0, temp_3, temp_2, temp_4, temp_6);\ + DUP2_ARG2(__lasx_xvilvh_h, temp_1, temp_0, temp_3, temp_2, temp_5, temp_7);\ + DUP2_ARG2(__lasx_xvilvl_w, temp_6, temp_4, temp_7, temp_5, out_0, out_2); \ + DUP2_ARG2(__lasx_xvilvh_w, temp_6, temp_4, temp_7, temp_5, out_1, out_3); \ +} + +#define LASX_IDCTROWCONDDC \ + const_val = 16383 * ((1 << 19) / 16383); \ + const_val1 = __lasx_xvreplgr2vr_w(const_val); \ + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, \ + in0, in1, in2, in3); \ + LASX_TRANSPOSE4x16(in0, in1, in2, in3, in0, in1, in2, in3); \ + a0 = __lasx_xvpermi_d(in0, 0xD8); \ + a0 = __lasx_vext2xv_w_h(a0); \ + temp = __lasx_xvslli_w(a0, 3); \ + a1 = __lasx_xvpermi_d(in0, 0x8D); \ + a1 = __lasx_vext2xv_w_h(a1); \ + a2 = __lasx_xvpermi_d(in1, 0xD8); \ + a2 = __lasx_vext2xv_w_h(a2); \ + a3 = __lasx_xvpermi_d(in1, 0x8D); \ + a3 = __lasx_vext2xv_w_h(a3); \ + b0 = __lasx_xvpermi_d(in2, 0xD8); \ + b0 = __lasx_vext2xv_w_h(b0); \ + b1 = __lasx_xvpermi_d(in2, 0x8D); \ + b1 = __lasx_vext2xv_w_h(b1); \ + b2 = __lasx_xvpermi_d(in3, 0xD8); \ + b2 = __lasx_vext2xv_w_h(b2); \ + b3 = __lasx_xvpermi_d(in3, 0x8D); \ + b3 = __lasx_vext2xv_w_h(b3); \ + select_vec = a0 | a1 | a2 | a3 | b0 | b1 | b2 | b3; \ + select_vec = __lasx_xvslti_wu(select_vec, 1); \ + \ + DUP4_ARG2(__lasx_xvrepl128vei_h, w1, 2, w1, 3, w1, 4, w1, 5, \ + w2, w3, w4, w5); \ + DUP2_ARG2(__lasx_xvrepl128vei_h, w1, 6, w1, 7, w6, w7); \ + w1 = __lasx_xvrepl128vei_h(w1, 1); \ + \ + /* part of FUNC6(idctRowCondDC) */ \ + temp0 = __lasx_xvmaddwl_w_h(const_val0, in0, w4); \ + DUP2_ARG2(__lasx_xvmulwl_w_h, in1, w2, in1, w6, temp1, temp2); \ + a0 = __lasx_xvadd_w(temp0, temp1); \ + a1 = __lasx_xvadd_w(temp0, temp2); \ + a2 = __lasx_xvsub_w(temp0, temp2); \ + a3 = __lasx_xvsub_w(temp0, temp1); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in1, in0, w3, w1, temp0, temp1); \ + b0 = __lasx_xvdp2_w_h(temp0, temp1); \ + temp1 = __lasx_xvneg_h(w7); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b1 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w5); \ + b2 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w5); \ + temp2 = __lasx_xvilvl_h(temp1, w7); \ + b3 = __lasx_xvdp2_w_h(temp0, temp2); \ + \ + /* if (AV_RAN64A(row + 4)) */ \ + DUP2_ARG2(__lasx_xvilvl_h, in3, in2, w6, w4, temp0, temp1); \ + a0 = __lasx_xvdp2add_w_h(a0, temp0, temp1); \ + temp1 = __lasx_xvilvl_h(w2, w4); \ + a1 = __lasx_xvdp2sub_w_h(a1, temp0, temp1); \ + temp1 = __lasx_xvneg_h(w4); \ + temp2 = __lasx_xvilvl_h(w2, temp1); \ + a2 = __lasx_xvdp2add_w_h(a2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w6); \ + temp2 = __lasx_xvilvl_h(temp1, w4); \ + a3 = __lasx_xvdp2add_w_h(a3, temp0, temp2); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in3, in2, w7, w5, temp0, temp1); \ + b0 = __lasx_xvdp2add_w_h(b0, temp0, temp1); \ + DUP2_ARG2(__lasx_xvilvl_h, w5, w1, w3, w7, temp1, temp2); \ + b1 = __lasx_xvdp2sub_w_h(b1, temp0, temp1); \ + b2 = __lasx_xvdp2add_w_h(b2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b3 = __lasx_xvdp2add_w_h(b3, temp0, temp2); \ + \ + DUP4_ARG2(__lasx_xvadd_w, a0, b0, a1, b1, a2, b2, a3, b3, \ + temp0, temp1, temp2, temp3); \ + DUP4_ARG2(__lasx_xvsub_w, a0, b0, a1, b1, a2, b2, a3, b3, \ + a0, a1, a2, a3); \ + DUP4_ARG2(__lasx_xvsrai_w, temp0, 11, temp1, 11, temp2, 11, temp3, 11, \ + temp0, temp1, temp2, temp3); \ + DUP4_ARG2(__lasx_xvsrai_w, a0, 11, a1, 11, a2, 11, a3, 11, a0, a1, a2, a3);\ + DUP4_ARG3(__lasx_xvbitsel_v, temp0, temp, select_vec, temp1, temp, \ + select_vec, temp2, temp, select_vec, temp3, temp, select_vec, \ + in0, in1, in2, in3); \ + DUP4_ARG3(__lasx_xvbitsel_v, a0, temp, select_vec, a1, temp, \ + select_vec, a2, temp, select_vec, a3, temp, select_vec, \ + a0, a1, a2, a3); \ + DUP4_ARG2(__lasx_xvpickev_h, in1, in0, in3, in2, a2, a3, a0, a1, \ + in0, in1, in2, in3); \ + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, \ + in0, in1, in2, in3); \ + +#define LASX_IDCTCOLS \ + /* part of FUNC6(idctSparaseCol) */ \ + LASX_TRANSPOSE4x16(in0, in1, in2, in3, in0, in1, in2, in3); \ + temp0 = __lasx_xvmaddwl_w_h(const_val1, in0, w4); \ + DUP2_ARG2(__lasx_xvmulwl_w_h, in1, w2, in1, w6, temp1, temp2); \ + a0 = __lasx_xvadd_w(temp0, temp1); \ + a1 = __lasx_xvadd_w(temp0, temp2); \ + a2 = __lasx_xvsub_w(temp0, temp2); \ + a3 = __lasx_xvsub_w(temp0, temp1); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in1, in0, w3, w1, temp0, temp1); \ + b0 = __lasx_xvdp2_w_h(temp0, temp1); \ + temp1 = __lasx_xvneg_h(w7); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b1 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w5); \ + b2 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w5); \ + temp2 = __lasx_xvilvl_h(temp1, w7); \ + b3 = __lasx_xvdp2_w_h(temp0, temp2); \ + \ + /* if (AV_RAN64A(row + 4)) */ \ + DUP2_ARG2(__lasx_xvilvl_h, in3, in2, w6, w4, temp0, temp1); \ + a0 = __lasx_xvdp2add_w_h(a0, temp0, temp1); \ + temp1 = __lasx_xvilvl_h(w2, w4); \ + a1 = __lasx_xvdp2sub_w_h(a1, temp0, temp1); \ + temp1 = __lasx_xvneg_h(w4); \ + temp2 = __lasx_xvilvl_h(w2, temp1); \ + a2 = __lasx_xvdp2add_w_h(a2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w6); \ + temp2 = __lasx_xvilvl_h(temp1, w4); \ + a3 = __lasx_xvdp2add_w_h(a3, temp0, temp2); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in3, in2, w7, w5, temp0, temp1); \ + b0 = __lasx_xvdp2add_w_h(b0, temp0, temp1); \ + DUP2_ARG2(__lasx_xvilvl_h, w5, w1, w3, w7, temp1, temp2); \ + b1 = __lasx_xvdp2sub_w_h(b1, temp0, temp1); \ + b2 = __lasx_xvdp2add_w_h(b2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b3 = __lasx_xvdp2add_w_h(b3, temp0, temp2); \ + \ + DUP4_ARG2(__lasx_xvadd_w, a0, b0, a1, b1, a2, b2, a3, b3, \ + temp0, temp1, temp2, temp3); \ + DUP4_ARG2(__lasx_xvsub_w, a3, b3, a2, b2, a1, b1, a0, b0, \ + a3, a2, a1, a0); \ + DUP4_ARG3(__lasx_xvsrani_h_w, temp1, temp0, 20, temp3, temp2, 20, a2, a3, \ + 20, a0, a1, 20, in0, in1, in2, in3); \ + +void ff_simple_idct_lasx(int16_t *block) +{ + int32_t const_val = 1 << 10; + __m256i w1 = {0x4B42539F58C50000, 0x11A822A332493FFF, + 0x4B42539F58C50000, 0x11A822A332493FFF}; + __m256i in0, in1, in2, in3; + __m256i w2, w3, w4, w5, w6, w7; + __m256i a0, a1, a2, a3; + __m256i b0, b1, b2, b3; + __m256i temp0, temp1, temp2, temp3; + __m256i const_val0 = __lasx_xvreplgr2vr_w(const_val); + __m256i const_val1, select_vec, temp; + + LASX_IDCTROWCONDDC + LASX_IDCTCOLS + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + __lasx_xvst(in0, block, 0); + __lasx_xvst(in1, block, 32); + __lasx_xvst(in2, block, 64); + __lasx_xvst(in3, block, 96); +} + +void ff_simple_idct_put_lasx(uint8_t *dst, ptrdiff_t dst_stride, + int16_t *block) +{ + int32_t const_val = 1 << 10; + ptrdiff_t dst_stride_2x = dst_stride << 1; + ptrdiff_t dst_stride_4x = dst_stride << 2; + ptrdiff_t dst_stride_3x = dst_stride_2x + dst_stride; + __m256i w1 = {0x4B42539F58C50000, 0x11A822A332493FFF, + 0x4B42539F58C50000, 0x11A822A332493FFF}; + __m256i in0, in1, in2, in3; + __m256i w2, w3, w4, w5, w6, w7; + __m256i a0, a1, a2, a3; + __m256i b0, b1, b2, b3; + __m256i temp0, temp1, temp2, temp3; + __m256i const_val0 = __lasx_xvreplgr2vr_w(const_val); + __m256i const_val1, select_vec, temp; + + LASX_IDCTROWCONDDC + LASX_IDCTCOLS + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + DUP4_ARG1(__lasx_xvclip255_h, in0, in1, in2, in3, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvpickev_b, in1, in0, in3, in2, in0, in1); + __lasx_xvstelm_d(in0, dst, 0, 0); + __lasx_xvstelm_d(in0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(in1, dst, 0, 0); + __lasx_xvstelm_d(in1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in1, dst + dst_stride_3x, 0, 3); +} + +void ff_simple_idct_add_lasx(uint8_t *dst, ptrdiff_t dst_stride, + int16_t *block) +{ + int32_t const_val = 1 << 10; + uint8_t *dst1 = dst; + ptrdiff_t dst_stride_2x = dst_stride << 1; + ptrdiff_t dst_stride_4x = dst_stride << 2; + ptrdiff_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m256i w1 = {0x4B42539F58C50000, 0x11A822A332493FFF, + 0x4B42539F58C50000, 0x11A822A332493FFF}; + __m256i sh = {0x0003000200010000, 0x000B000A00090008, + 0x0007000600050004, 0x000F000E000D000C}; + __m256i in0, in1, in2, in3; + __m256i w2, w3, w4, w5, w6, w7; + __m256i a0, a1, a2, a3; + __m256i b0, b1, b2, b3; + __m256i temp0, temp1, temp2, temp3; + __m256i const_val0 = __lasx_xvreplgr2vr_w(const_val); + __m256i const_val1, select_vec, temp; + + LASX_IDCTROWCONDDC + LASX_IDCTCOLS + a0 = __lasx_xvldrepl_d(dst1, 0); + a0 = __lasx_vext2xv_hu_bu(a0); + dst1 += dst_stride; + a1 = __lasx_xvldrepl_d(dst1, 0); + a1 = __lasx_vext2xv_hu_bu(a1); + dst1 += dst_stride; + a2 = __lasx_xvldrepl_d(dst1, 0); + a2 = __lasx_vext2xv_hu_bu(a2); + dst1 += dst_stride; + a3 = __lasx_xvldrepl_d(dst1, 0); + a3 = __lasx_vext2xv_hu_bu(a3); + dst1 += dst_stride; + b0 = __lasx_xvldrepl_d(dst1, 0); + b0 = __lasx_vext2xv_hu_bu(b0); + dst1 += dst_stride; + b1 = __lasx_xvldrepl_d(dst1, 0); + b1 = __lasx_vext2xv_hu_bu(b1); + dst1 += dst_stride; + b2 = __lasx_xvldrepl_d(dst1, 0); + b2 = __lasx_vext2xv_hu_bu(b2); + dst1 += dst_stride; + b3 = __lasx_xvldrepl_d(dst1, 0); + b3 = __lasx_vext2xv_hu_bu(b3); + DUP4_ARG3(__lasx_xvshuf_h, sh, a1, a0, sh, a3, a2, sh, b1, b0, sh, b3, b2, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvadd_h, temp0, in0, temp1, in1, temp2, in2, temp3, in3, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + DUP4_ARG1(__lasx_xvclip255_h, in0, in1, in2, in3, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvpickev_b, in1, in0, in3, in2, in0, in1); + __lasx_xvstelm_d(in0, dst, 0, 0); + __lasx_xvstelm_d(in0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(in1, dst, 0, 0); + __lasx_xvstelm_d(in1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in1, dst + dst_stride_3x, 0, 3); +} From 8ca7d474c19f856b28fa588e040b23b1a58368ed Mon Sep 17 00:00:00 2001 From: gxw Date: Wed, 29 Dec 2021 18:18:22 +0800 Subject: [PATCH 720/894] avcodec: [loongarch] Optimize prefetch with loongarch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./ffmpeg -i ../1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before:296 after :308 Reviewed-by: 殷时友 Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 1 + libavcodec/loongarch/videodsp_init.c | 45 ++++++++++++++++++++++++++++ libavcodec/videodsp.c | 2 ++ libavcodec/videodsp.h | 1 + 4 files changed, 49 insertions(+) create mode 100644 libavcodec/loongarch/videodsp_init.c diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index c4d71e801b..3c15c2edeb 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -7,6 +7,7 @@ OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o OBJS-$(CONFIG_VC1DSP) += loongarch/vc1dsp_init_loongarch.o OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_init_loongarch.o OBJS-$(CONFIG_IDCTDSP) += loongarch/idctdsp_init_loongarch.o +OBJS-$(CONFIG_VIDEODSP) += loongarch/videodsp_init.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ diff --git a/libavcodec/loongarch/videodsp_init.c b/libavcodec/loongarch/videodsp_init.c new file mode 100644 index 0000000000..6cbb7763ff --- /dev/null +++ b/libavcodec/loongarch/videodsp_init.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Xiwei Gu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/videodsp.h" +#include "libavutil/attributes.h" + +static void prefetch_loongarch(uint8_t *mem, ptrdiff_t stride, int h) +{ + register const uint8_t *p = mem; + + __asm__ volatile ( + "1: \n\t" + "preld 0, %[p], 0 \n\t" + "preld 0, %[p], 32 \n\t" + "addi.d %[h], %[h], -1 \n\t" + "add.d %[p], %[p], %[stride] \n\t" + + "blt $r0, %[h], 1b \n\t" + : [p] "+r" (p), [h] "+r" (h) + : [stride] "r" (stride) + ); +} + +av_cold void ff_videodsp_init_loongarch(VideoDSPContext *ctx, int bpc) +{ + ctx->prefetch = prefetch_loongarch; +} diff --git a/libavcodec/videodsp.c b/libavcodec/videodsp.c index ce9e9eb143..212147984f 100644 --- a/libavcodec/videodsp.c +++ b/libavcodec/videodsp.c @@ -54,4 +54,6 @@ av_cold void ff_videodsp_init(VideoDSPContext *ctx, int bpc) ff_videodsp_init_x86(ctx, bpc); if (ARCH_MIPS) ff_videodsp_init_mips(ctx, bpc); + if (ARCH_LOONGARCH64) + ff_videodsp_init_loongarch(ctx, bpc); } diff --git a/libavcodec/videodsp.h b/libavcodec/videodsp.h index c0545f22b0..ac971dc57f 100644 --- a/libavcodec/videodsp.h +++ b/libavcodec/videodsp.h @@ -84,5 +84,6 @@ void ff_videodsp_init_arm(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_ppc(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_mips(VideoDSPContext *ctx, int bpc); +void ff_videodsp_init_loongarch(VideoDSPContext *ctx, int bpc); #endif /* AVCODEC_VIDEODSP_H */ From 0b670a7f915fd4fa86444da7c24f325d651b16bd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 21 Dec 2021 21:23:00 +0100 Subject: [PATCH 721/894] avcodec/mjpegenc: Use custom close function directly Currently, ff_mpv_encode_end() is the close function of the two MJPEG-based encoders; it calls ff_mjpeg_encode_close() for them which adds a check to the generic code. This commit reverses the order of this relationship: The MJPEG encoders directly use a custom close function which in turn calls ff_mpv_encode_end(). This avoids the branch in ff_mpv_encode_end() and makes the generic code more generic. Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 9 ++++++--- libavcodec/mjpegenc.h | 1 - libavcodec/mpegvideo_enc.c | 3 --- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 30cbbddb59..05b6130de4 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -320,12 +320,15 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) return 0; } -av_cold void ff_mjpeg_encode_close(MpegEncContext *s) +static av_cold int mjpeg_encode_close(AVCodecContext *avctx) { + MpegEncContext *const s = avctx->priv_data; if (s->mjpeg_ctx) { av_freep(&s->mjpeg_ctx->huff_buffer); av_freep(&s->mjpeg_ctx); } + ff_mpv_encode_end(avctx); + return 0; } /** @@ -618,7 +621,7 @@ const AVCodec ff_mjpeg_encoder = { .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, + .close = mjpeg_encode_close, .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { @@ -647,7 +650,7 @@ const AVCodec ff_amv_encoder = { .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, .encode2 = amv_encode_picture, - .close = ff_mpv_encode_end, + .close = mjpeg_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 2e92511276..bc9b017e7a 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -105,7 +105,6 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code) } int ff_mjpeg_encode_init(MpegEncContext *s); -void ff_mjpeg_encode_close(MpegEncContext *s); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); int ff_mjpeg_encode_stuffing(MpegEncContext *s); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 128d1a327c..d2520368e1 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -970,9 +970,6 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) ff_rate_control_uninit(s); ff_mpv_common_end(s); - if ((CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER) && - s->out_format == FMT_MJPEG) - ff_mjpeg_encode_close(s); for (i = 0; i < FF_ARRAY_ELEMS(s->tmp_frames); i++) av_frame_free(&s->tmp_frames[i]); From 26e117a14dca123e00237e471abf9aa3e5eea812 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 21 Dec 2021 22:39:30 +0100 Subject: [PATCH 722/894] avcodec/mjpegenc: Avoid allocation of MJpegContext This is possible by allocating it together with the MpegEncContext. Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 31 +++++++++++++++++-------------- libavcodec/mjpegenc_common.c | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 05b6130de4..c4c45c885b 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -41,6 +41,15 @@ #include "mjpegenc.h" #include "profiles.h" +/* The following is the private context of MJPEG/AMV decoder. + * Note that when using slice threading only the main thread's + * MpegEncContext is followed by a MjpegContext; the other threads + * can access this shared context via MpegEncContext.mjpeg. */ +typedef struct MJPEGEncContext { + MpegEncContext mpeg; + MJpegContext mjpeg; +} MJPEGEncContext; + static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], uint8_t *uni_ac_vlc_len) { @@ -260,9 +269,11 @@ static int alloc_huffman(MpegEncContext *s) av_cold int ff_mjpeg_encode_init(MpegEncContext *s) { - MJpegContext *m; + MJpegContext *const m = &((MJPEGEncContext*)s)->mjpeg; int ret; + s->mjpeg_ctx = m; + av_assert0(s->slice_context_count == 1); /* The following check is automatically true for AMV, @@ -276,10 +287,6 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) return AVERROR(EINVAL); } - m = av_mallocz(sizeof(MJpegContext)); - if (!m) - return AVERROR(ENOMEM); - s->min_qcoeff=-1023; s->max_qcoeff= 1023; @@ -312,7 +319,6 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) // Buffers start out empty. m->huff_ncode = 0; - s->mjpeg_ctx = m; if(s->huffman == HUFFMAN_TABLE_OPTIMAL) return alloc_huffman(s); @@ -322,11 +328,8 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) static av_cold int mjpeg_encode_close(AVCodecContext *avctx) { - MpegEncContext *const s = avctx->priv_data; - if (s->mjpeg_ctx) { - av_freep(&s->mjpeg_ctx->huff_buffer); - av_freep(&s->mjpeg_ctx); - } + MJPEGEncContext *const mjpeg = avctx->priv_data; + av_freep(&mjpeg->mjpeg.huff_buffer); ff_mpv_encode_end(avctx); return 0; } @@ -377,7 +380,7 @@ static void ff_mjpeg_encode_coef(MJpegContext *s, uint8_t table_id, int val, int /** * Add the block's data into the JPEG buffer. * - * @param s The MJpegEncContext that contains the JPEG buffer. + * @param s The MpegEncContext that contains the JPEG buffer. * @param block The block. * @param n The block's index or number. */ @@ -618,7 +621,7 @@ const AVCodec ff_mjpeg_encoder = { .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MJPEG, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MJPEGEncContext), .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = mjpeg_encode_close, @@ -647,7 +650,7 @@ const AVCodec ff_amv_encoder = { .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_AMV, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MJPEGEncContext), .init = ff_mpv_encode_init, .encode2 = amv_encode_picture, .close = mjpeg_encode_close, diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 368e87128c..ba5c5320d7 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -323,7 +323,7 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, end: if (!lossless) { MpegEncContext *s = avctx->priv_data; - av_assert0(avctx->codec->priv_data_size == sizeof(MpegEncContext)); + av_assert0(avctx->codec->priv_data_size > sizeof(MpegEncContext)); s->esc_pos = put_bytes_count(pb, 0); for(i=1; islice_context_count; i++) From 4d39a4db68b564c359c0c561e456b75f755b901f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 21 Dec 2021 23:14:29 +0100 Subject: [PATCH 723/894] avcodec/mpegvideo_enc: Move MJPEG init checks to mjpegenc.c Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 10 ++++++++++ libavcodec/mpegvideo_enc.c | 12 ------------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index c4c45c885b..57f249f56e 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -276,6 +276,16 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) av_assert0(s->slice_context_count == 1); + if (s->codec_id == AV_CODEC_ID_AMV || (s->avctx->active_thread_type & FF_THREAD_SLICE)) + s->huffman = 0; + + if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { + // Used to produce garbage with MJPEG. + av_log(s->avctx, AV_LOG_ERROR, + "QP RD is no longer compatible with MJPEG or AMV\n"); + return AVERROR(EINVAL); + } + /* The following check is automatically true for AMV, * but it doesn't hurt either. */ ret = ff_mjpeg_encode_check_pix_fmt(s->avctx); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index d2520368e1..7e45fd0ff3 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -370,9 +370,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->codec_id == AV_CODEC_ID_AMV || (avctx->active_thread_type & FF_THREAD_SLICE)) - s->huffman = 0; - if (s->intra_dc_precision > (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 3 : 0)) { av_log(avctx, AV_LOG_ERROR, "intra dc precision too large\n"); return AVERROR(EINVAL); @@ -573,15 +570,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && - (s->codec_id == AV_CODEC_ID_AMV || - s->codec_id == AV_CODEC_ID_MJPEG)) { - // Used to produce garbage with MJPEG. - av_log(avctx, AV_LOG_ERROR, - "QP RD is no longer compatible with MJPEG or AMV\n"); - return AVERROR(EINVAL); - } - if (s->scenechange_threshold < 1000000000 && (avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) { av_log(avctx, AV_LOG_ERROR, From be736e42372ddb311ff6d7bf8898f67bf3a20793 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 21 Dec 2021 23:20:19 +0100 Subject: [PATCH 724/894] avcodec/mpegvideo_enc: Remove redundant checks for multithreading The generic code ensures that only codecs with the FF_CODEC_CAP_AUTO_THREADS internal cap ever have to handle the case avctx->thread_count == 0 themselves; moreover, it is also ensured generically that only codecs that support some form of threading have thread_count set to something else than one. So these checks are unnecessary. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 7e45fd0ff3..23e8a41a86 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -607,24 +607,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->thread_count > 1 && - s->codec_id != AV_CODEC_ID_MPEG4 && - s->codec_id != AV_CODEC_ID_MPEG1VIDEO && - s->codec_id != AV_CODEC_ID_MPEG2VIDEO && - s->codec_id != AV_CODEC_ID_MJPEG && - (s->codec_id != AV_CODEC_ID_H263P)) { - av_log(avctx, AV_LOG_ERROR, - "multi threaded encoding not supported by codec\n"); - return AVERROR_PATCHWELCOME; - } - - if (avctx->thread_count < 1) { - av_log(avctx, AV_LOG_ERROR, - "automatic thread number detection not supported by codec, " - "patch welcome\n"); - return AVERROR_PATCHWELCOME; - } - if (s->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) { av_log(avctx, AV_LOG_INFO, "notice: b_frame_strategy only affects the first pass\n"); From 410af1caa34838ab36ceeab83f82b0ef8df823ba Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 01:03:46 +0100 Subject: [PATCH 725/894] avcodec/mjpegenc: Add wrapper for ff_mjpeg_encode_picture_header() This factors the translation from MpegEncContext out and will enable further optimizations in the next commits. Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 16 ++++++++++++++-- libavcodec/mjpegenc.h | 1 + libavcodec/mpegvideo_enc.c | 5 +---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 57f249f56e..152919f4c8 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -74,6 +74,19 @@ static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], } } +static void mjpeg_encode_picture_header(MpegEncContext *s) +{ + ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, + s->pred, s->intra_matrix, s->chroma_intra_matrix); +} + +void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s) +{ + /* s->huffman == HUFFMAN_TABLE_OPTIMAL can only be true for MJPEG. */ + if (!CONFIG_MJPEG_ENCODER || s->huffman != HUFFMAN_TABLE_OPTIMAL) + mjpeg_encode_picture_header(s); +} + #if CONFIG_MJPEG_ENCODER /** * Encodes and outputs the entire frame in the JPEG format. @@ -213,8 +226,7 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s) s->intra_chroma_ac_vlc_length = s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; - ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - s->pred, s->intra_matrix, s->chroma_intra_matrix); + mjpeg_encode_picture_header(s); mjpeg_encode_picture_frame(s); } #endif diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index bc9b017e7a..555677e69a 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -105,6 +105,7 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code) } int ff_mjpeg_encode_init(MpegEncContext *s); +void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); int ff_mjpeg_encode_stuffing(MpegEncContext *s); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 23e8a41a86..9807e491e5 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3702,10 +3702,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) switch(s->out_format) { #if CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER case FMT_MJPEG: - /* s->huffman == HUFFMAN_TABLE_OPTIMAL can only be true for MJPEG. */ - if (!CONFIG_MJPEG_ENCODER || s->huffman != HUFFMAN_TABLE_OPTIMAL) - ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - s->pred, s->intra_matrix, s->chroma_intra_matrix); + ff_mjpeg_amv_encode_picture_header(s); break; #endif case FMT_SPEEDHQ: From 8edb2c638cb2970585ad4bc1a5dc632bdc85ae45 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 01:13:53 +0100 Subject: [PATCH 726/894] avcodec/mjpegenc_common: Move code for MJPEG/AMV to mjpegenc Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 4 ++++ libavcodec/mjpegenc_common.c | 14 ++------------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 152919f4c8..89b22ab42d 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -78,6 +78,10 @@ static void mjpeg_encode_picture_header(MpegEncContext *s) { ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, s->pred, s->intra_matrix, s->chroma_intra_matrix); + + s->esc_pos = put_bytes_count(&s->pb, 0); + for (int i = 1; i < s->slice_context_count; i++) + s->thread_context[i]->esc_pos = 0; } void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s) diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index ba5c5320d7..86a9791477 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -224,7 +224,6 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, { const int lossless = avctx->codec_id != AV_CODEC_ID_MJPEG && avctx->codec_id != AV_CODEC_ID_AMV; int hsample[4], vsample[4]; - int i; int components = 3 + (avctx->pix_fmt == AV_PIX_FMT_BGRA); int chroma_matrix = !!memcmp(luma_intra_matrix, chroma_intra_matrix, @@ -235,7 +234,8 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, put_marker(pb, SOI); // hack for AMV mjpeg format - if(avctx->codec_id == AV_CODEC_ID_AMV) goto end; + if (avctx->codec_id == AV_CODEC_ID_AMV) + return; jpeg_put_comments(avctx, pb); @@ -319,16 +319,6 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, } put_bits(pb, 8, 0); /* Ah/Al (not used) */ - -end: - if (!lossless) { - MpegEncContext *s = avctx->priv_data; - av_assert0(avctx->codec->priv_data_size > sizeof(MpegEncContext)); - - s->esc_pos = put_bytes_count(pb, 0); - for(i=1; islice_context_count; i++) - s->thread_context[i]->esc_pos = 0; - } } void ff_mjpeg_escape_FF(PutBitContext *pb, int start) From 506758357e21f4500e160496734d1128c68a8983 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 01:31:56 +0100 Subject: [PATCH 727/894] avcodec/mjpegenc_common: Fix intendation Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc_common.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 86a9791477..049a8f4d25 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -73,17 +73,17 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, int matrix_count = 1 + !!memcmp(luma_intra_matrix, chroma_intra_matrix, sizeof(luma_intra_matrix[0]) * 64); - if (s && s->force_duplicated_matrix) - matrix_count = 2; - /* quant matrixes */ - put_marker(p, DQT); - put_bits(p, 16, 2 + matrix_count * (1 + 64)); - put_bits(p, 4, 0); /* 8 bit precision */ - put_bits(p, 4, 0); /* table 0 */ - for(i=0;i<64;i++) { - j = intra_scantable->permutated[i]; - put_bits(p, 8, luma_intra_matrix[j]); - } + if (s && s->force_duplicated_matrix) + matrix_count = 2; + /* quant matrixes */ + put_marker(p, DQT); + put_bits(p, 16, 2 + matrix_count * (1 + 64)); + put_bits(p, 4, 0); /* 8 bit precision */ + put_bits(p, 4, 0); /* table 0 */ + for (int i = 0; i < 64; i++) { + uint8_t j = intra_scantable->permutated[i]; + put_bits(p, 8, luma_intra_matrix[j]); + } if (matrix_count > 1) { put_bits(p, 4, 0); /* 8 bit precision */ From bd2ec3d3454f4fea8c4362faff993ee1ab7a30ff Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 02:05:48 +0100 Subject: [PATCH 728/894] avcodec/mpegvideo: Move MJPEG/AMV-only fields to MJpegContext This is possible now that MJpegContext is allocated jointly with MpegEncContext as part of the AVCodecContext's private data. Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 18 ++++++++++-------- libavcodec/mjpegenc.h | 3 +++ libavcodec/mjpegenc_common.c | 4 ++-- libavcodec/mpegvideo.h | 8 +++++--- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 89b22ab42d..ed2ca79abe 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -86,8 +86,10 @@ static void mjpeg_encode_picture_header(MpegEncContext *s) void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s) { + MJPEGEncContext *const m = (MJPEGEncContext*)s; + av_assert2(s->mjpeg_ctx == &m->mjpeg); /* s->huffman == HUFFMAN_TABLE_OPTIMAL can only be true for MJPEG. */ - if (!CONFIG_MJPEG_ENCODER || s->huffman != HUFFMAN_TABLE_OPTIMAL) + if (!CONFIG_MJPEG_ENCODER || m->mjpeg.huffman != HUFFMAN_TABLE_OPTIMAL) mjpeg_encode_picture_header(s); } @@ -211,13 +213,13 @@ static void mjpeg_build_optimal_huffman(MJpegContext *m) */ int ff_mjpeg_encode_stuffing(MpegEncContext *s) { + MJpegContext *const m = s->mjpeg_ctx; PutBitContext *pbc = &s->pb; int mb_y = s->mb_y - !s->mb_x; int ret; #if CONFIG_MJPEG_ENCODER - if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { - MJpegContext *m = s->mjpeg_ctx; + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) { mjpeg_build_optimal_huffman(m); @@ -293,7 +295,7 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) av_assert0(s->slice_context_count == 1); if (s->codec_id == AV_CODEC_ID_AMV || (s->avctx->active_thread_type & FF_THREAD_SLICE)) - s->huffman = 0; + m->huffman = HUFFMAN_TABLE_DEFAULT; if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { // Used to produce garbage with MJPEG. @@ -346,7 +348,7 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) // Buffers start out empty. m->huff_ncode = 0; - if(s->huffman == HUFFMAN_TABLE_OPTIMAL) + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) return alloc_huffman(s); return 0; @@ -514,7 +516,7 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]) { int i; - if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { + if (s->mjpeg_ctx->huffman == HUFFMAN_TABLE_OPTIMAL) { if (s->chroma_format == CHROMA_444) { record_block(s, block[0], 0); record_block(s, block[2], 2); @@ -614,11 +616,11 @@ static int amv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, } #endif -#define OFFSET(x) offsetof(MpegEncContext, x) +#define OFFSET(x) offsetof(MJPEGEncContext, mjpeg.x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { FF_MPV_COMMON_OPTS -{ "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, +{ "pred", "Prediction method", FF_MPV_OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" }, diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 555677e69a..a593b67e96 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -57,6 +57,9 @@ typedef struct MJpegHuffmanCode { * Holds JPEG frame data and Huffman table data. */ typedef struct MJpegContext { + int huffman; + /* Force duplication of mjpeg matrices, useful for rtp streaming */ + int force_duplicated_matrix; //FIXME use array [3] instead of lumi / chroma, for easier addressing uint8_t huff_size_dc_luminance[12]; ///< DC luminance Huffman table size. uint16_t huff_code_dc_luminance[12]; ///< DC luminance Huffman table codes. diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 049a8f4d25..5058fc9113 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -73,7 +73,7 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, int matrix_count = 1 + !!memcmp(luma_intra_matrix, chroma_intra_matrix, sizeof(luma_intra_matrix[0]) * 64); - if (s && s->force_duplicated_matrix) + if (s && s->mjpeg_ctx->force_duplicated_matrix) matrix_count = 2; /* quant matrixes */ put_marker(p, DQT); @@ -110,7 +110,7 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, // Only MJPEG can have a variable Huffman variable. All other // formats use the default Huffman table. - if (s && s->huffman == HUFFMAN_TABLE_OPTIMAL) { + if (s && s->mjpeg_ctx->huffman == HUFFMAN_TABLE_OPTIMAL) { size += put_huffman_table(p, 0, 0, s->mjpeg_ctx->bits_dc_luminance, s->mjpeg_ctx->val_dc_luminance); size += put_huffman_table(p, 0, 1, s->mjpeg_ctx->bits_dc_chrominance, diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 879b019ffc..5a3486d74c 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -290,7 +290,6 @@ typedef struct MpegEncContext { uint16_t chroma_intra_matrix[64]; uint16_t inter_matrix[64]; uint16_t chroma_inter_matrix[64]; - int force_duplicated_matrix; ///< Force duplication of mjpeg matrices, useful for rtp streaming int intra_quant_bias; ///< bias for the quantizer int inter_quant_bias; ///< bias for the quantizer @@ -414,7 +413,6 @@ typedef struct MpegEncContext { struct MJpegContext *mjpeg_ctx; int esc_pos; int pred; - int huffman; /* MSMPEG4 specific */ int mv_table_index; @@ -575,6 +573,10 @@ typedef struct MpegEncContext { int noise_reduction; int intra_penalty; + +#if FF_API_MPEGVIDEO_OPTS + int dummy; ///< used as target for deprecated options +#endif } MpegEncContext; /* mpegvideo_enc common options */ @@ -664,7 +666,7 @@ FF_MPV_OPT_CMP_FUNC, \ #define FF_MPV_DEPRECATED_A53_CC_OPT \ { "a53cc", "Deprecated, does nothing", FF_MPV_OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, #define FF_MPV_DEPRECATED_MATRIX_OPT \ - { "force_duplicated_matrix", "Deprecated, does nothing", FF_MPV_OFFSET(force_duplicated_matrix), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, + { "force_duplicated_matrix", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, #define FF_MPV_DEPRECATED_BFRAME_OPTS \ { "b_strategy", "Deprecated, does nothing", FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, \ { "b_sensitivity", "Deprecated, does nothing", FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, { .i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, \ From 7aee9e326f7f3105f9477d92742edae6d83c9a14 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 00:46:39 +0100 Subject: [PATCH 729/894] avcodec/mjpegenc: Deprecate unused prediction type Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc.c | 6 ++++-- libavcodec/mjpegenc_common.c | 2 +- libavcodec/mpegvideo.h | 3 +-- libavcodec/version.h | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index ed2ca79abe..be3671d13c 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -77,7 +77,7 @@ static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], static void mjpeg_encode_picture_header(MpegEncContext *s) { ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - s->pred, s->intra_matrix, s->chroma_intra_matrix); + 0, s->intra_matrix, s->chroma_intra_matrix); s->esc_pos = put_bytes_count(&s->pb, 0); for (int i = 1; i < s->slice_context_count; i++) @@ -620,10 +620,12 @@ static int amv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { FF_MPV_COMMON_OPTS -{ "pred", "Prediction method", FF_MPV_OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, +#if FF_API_MJPEG_PRED +{ "pred", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" }, +#endif { "huffman", "Huffman table strategy", OFFSET(huffman), AV_OPT_TYPE_INT, { .i64 = HUFFMAN_TABLE_OPTIMAL }, 0, NB_HUFFMAN_TABLE_OPTION - 1, VE, "huffman" }, { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = HUFFMAN_TABLE_DEFAULT }, INT_MIN, INT_MAX, VE, "huffman" }, { "optimal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = HUFFMAN_TABLE_OPTIMAL }, INT_MIN, INT_MAX, VE, "huffman" }, diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 5058fc9113..924bb4e689 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -310,7 +310,7 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, put_bits(pb, 4, 0); /* AC huffman table index */ } - put_bits(pb, 8, lossless ? pred : 0); /* Ss (not used) */ + put_bits(pb, 8, pred); /* Ss (not used); pred only nonzero for LJPEG */ switch (avctx->codec_id) { case AV_CODEC_ID_MJPEG: put_bits(pb, 8, 63); break; /* Se (not used) */ diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 5a3486d74c..942b05ba37 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -412,7 +412,6 @@ typedef struct MpegEncContext { /* MJPEG specific */ struct MJpegContext *mjpeg_ctx; int esc_pos; - int pred; /* MSMPEG4 specific */ int mv_table_index; @@ -574,7 +573,7 @@ typedef struct MpegEncContext { int intra_penalty; -#if FF_API_MPEGVIDEO_OPTS +#if FF_API_MPEGVIDEO_OPTS || FF_API_MJPEG_PRED int dummy; ///< used as target for deprecated options #endif } MpegEncContext; diff --git a/libavcodec/version.h b/libavcodec/version.h index fb1a0feec6..a46fb05f1a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 19 +#define LIBAVCODEC_VERSION_MINOR 20 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -63,5 +63,6 @@ #define FF_API_MPEGVIDEO_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_MJPEG_PRED (LIBAVCODEC_VERSION_MAJOR < 60) #endif /* AVCODEC_VERSION_H */ From 8a0981d0131e648c84e9996bd024d5cdbd791599 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 02:28:04 +0100 Subject: [PATCH 730/894] avcodec/mjpegenc_common: Pass MJpegContext for writing picture header It is the structure that is actually used. Signed-off-by: Andreas Rheinhardt --- libavcodec/ljpegenc.c | 2 +- libavcodec/mjpegenc.c | 5 +++-- libavcodec/mjpegenc_common.c | 34 ++++++++++++++++------------------ libavcodec/mjpegenc_common.h | 3 +++ 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index ecdedeb6a3..e15f448f90 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -238,7 +238,7 @@ static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, init_put_bits(&pb, pkt->data, pkt->size); - ff_mjpeg_encode_picture_header(avctx, &pb, &s->scantable, + ff_mjpeg_encode_picture_header(avctx, &pb, NULL, &s->scantable, s->pred, s->matrix, s->matrix); header_bits = put_bits_count(&pb); diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index be3671d13c..d15b9ece50 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -76,8 +76,9 @@ static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], static void mjpeg_encode_picture_header(MpegEncContext *s) { - ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - 0, s->intra_matrix, s->chroma_intra_matrix); + ff_mjpeg_encode_picture_header(s->avctx, &s->pb, s->mjpeg_ctx, + &s->intra_scantable, 0, + s->intra_matrix, s->chroma_intra_matrix); s->esc_pos = put_bytes_count(&s->pb, 0); for (int i = 1; i < s->slice_context_count; i++) diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 924bb4e689..d75ae6b6a7 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -56,6 +56,7 @@ static int put_huffman_table(PutBitContext *p, int table_class, int table_id, } static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, + MJpegContext *m, ScanTable *intra_scantable, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64], @@ -63,17 +64,12 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, { int i, j, size; uint8_t *ptr; - MpegEncContext *s = NULL; - /* Since avctx->priv_data will point to LJpegEncContext in this case */ - if (avctx->codec_id != AV_CODEC_ID_LJPEG) - s = avctx->priv_data; - - if (avctx->codec_id != AV_CODEC_ID_LJPEG) { + if (m) { int matrix_count = 1 + !!memcmp(luma_intra_matrix, chroma_intra_matrix, sizeof(luma_intra_matrix[0]) * 64); - if (s && s->mjpeg_ctx->force_duplicated_matrix) + if (m->force_duplicated_matrix) matrix_count = 2; /* quant matrixes */ put_marker(p, DQT); @@ -110,16 +106,16 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, // Only MJPEG can have a variable Huffman variable. All other // formats use the default Huffman table. - if (s && s->mjpeg_ctx->huffman == HUFFMAN_TABLE_OPTIMAL) { - size += put_huffman_table(p, 0, 0, s->mjpeg_ctx->bits_dc_luminance, - s->mjpeg_ctx->val_dc_luminance); - size += put_huffman_table(p, 0, 1, s->mjpeg_ctx->bits_dc_chrominance, - s->mjpeg_ctx->val_dc_chrominance); + if (m && m->huffman == HUFFMAN_TABLE_OPTIMAL) { + size += put_huffman_table(p, 0, 0, m->bits_dc_luminance, + m->val_dc_luminance); + size += put_huffman_table(p, 0, 1, m->bits_dc_chrominance, + m->val_dc_chrominance); - size += put_huffman_table(p, 1, 0, s->mjpeg_ctx->bits_ac_luminance, - s->mjpeg_ctx->val_ac_luminance); - size += put_huffman_table(p, 1, 1, s->mjpeg_ctx->bits_ac_chrominance, - s->mjpeg_ctx->val_ac_chrominance); + size += put_huffman_table(p, 1, 0, m->bits_ac_luminance, + m->val_ac_luminance); + size += put_huffman_table(p, 1, 1, m->bits_ac_chrominance, + m->val_ac_chrominance); } else { size += put_huffman_table(p, 0, 0, ff_mjpeg_bits_dc_luminance, ff_mjpeg_val_dc); @@ -218,11 +214,12 @@ void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4 } void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + MJpegContext *m, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64]) { - const int lossless = avctx->codec_id != AV_CODEC_ID_MJPEG && avctx->codec_id != AV_CODEC_ID_AMV; + const int lossless = !m; int hsample[4], vsample[4]; int components = 3 + (avctx->pix_fmt == AV_PIX_FMT_BGRA); int chroma_matrix = !!memcmp(luma_intra_matrix, @@ -239,7 +236,8 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, jpeg_put_comments(avctx, pb); - jpeg_table_header(avctx, pb, intra_scantable, luma_intra_matrix, chroma_intra_matrix, hsample); + jpeg_table_header(avctx, pb, m, intra_scantable, + luma_intra_matrix, chroma_intra_matrix, hsample); switch (avctx->codec_id) { case AV_CODEC_ID_MJPEG: put_marker(pb, SOF0 ); break; diff --git a/libavcodec/mjpegenc_common.h b/libavcodec/mjpegenc_common.h index 76c236d835..ac753bf153 100644 --- a/libavcodec/mjpegenc_common.h +++ b/libavcodec/mjpegenc_common.h @@ -27,7 +27,10 @@ #include "idctdsp.h" #include "put_bits.h" +struct MJpegContext; + void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + struct MJpegContext *m, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64]); From 3867b18120e11174b3d775699ce74339b0b1bc4c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 03:39:16 +0100 Subject: [PATCH 731/894] avcodec/mjpegenc_common: Don't call function unnecessarily Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc_common.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index d75ae6b6a7..27438df5eb 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -188,10 +188,6 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4]) { - int chroma_h_shift, chroma_v_shift; - - av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, - &chroma_v_shift); if (avctx->codec->id == AV_CODEC_ID_LJPEG && ( avctx->pix_fmt == AV_PIX_FMT_BGR0 || avctx->pix_fmt == AV_PIX_FMT_BGRA @@ -204,6 +200,9 @@ void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4 vsample[0] = vsample[1] = vsample[2] = 2; hsample[0] = hsample[1] = hsample[2] = 1; } else { + int chroma_h_shift, chroma_v_shift; + av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, + &chroma_v_shift); vsample[0] = 2; vsample[1] = 2 >> chroma_v_shift; vsample[2] = 2 >> chroma_v_shift; From cbbd5e063dc5f2d4778e46c4d284a90512893007 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 03:41:48 +0100 Subject: [PATCH 732/894] avcodec/mjpegenc_common: Use AVCodecContext.codec_id directly Signed-off-by: Andreas Rheinhardt --- libavcodec/mjpegenc_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 27438df5eb..995e2b7670 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -188,7 +188,7 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4]) { - if (avctx->codec->id == AV_CODEC_ID_LJPEG && + if (avctx->codec_id == AV_CODEC_ID_LJPEG && ( avctx->pix_fmt == AV_PIX_FMT_BGR0 || avctx->pix_fmt == AV_PIX_FMT_BGRA || avctx->pix_fmt == AV_PIX_FMT_BGR24)) { From 4707023a95cfa56824a1f0c2bcb4ffa3acc37af6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 04:07:14 +0100 Subject: [PATCH 733/894] avcodec/mpegvideo: Remove unnecessary headers Signed-off-by: Andreas Rheinhardt --- libavcodec/eatqi.c | 1 + libavcodec/mdec.c | 1 + libavcodec/mpegvideo.c | 3 --- libavcodec/mpegvideo.h | 3 +-- libavcodec/mpegvideo_enc.c | 1 + libavcodec/mpegvideo_parser.c | 1 + libavcodec/speedhqenc.c | 1 + 7 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c index 9beab58a83..8f502b3c56 100644 --- a/libavcodec/eatqi.c +++ b/libavcodec/eatqi.c @@ -37,6 +37,7 @@ #include "idctdsp.h" #include "internal.h" #include "mpeg12.h" +#include "mpeg12data.h" typedef struct TqiContext { AVCodecContext *avctx; diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 39efed69b1..007e7fada8 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -34,6 +34,7 @@ #include "bswapdsp.h" #include "idctdsp.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "thread.h" typedef struct MDECContext { diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index a974650133..657970a450 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -31,7 +31,6 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" -#include "libavutil/motion_vector.h" #include "libavutil/video_enc_params.h" #include "avcodec.h" @@ -44,8 +43,6 @@ #include "mpegutils.h" #include "mpegvideo.h" #include "mpegvideodata.h" -#include "mjpegenc.h" -#include "msmpeg4.h" #include "qpeldsp.h" #include "thread.h" #include "wmv2.h" diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 942b05ba37..d810f900f2 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -53,9 +53,8 @@ #include "parser.h" #endif #include "mpegutils.h" -#include "mpeg12data.h" #include "qpeldsp.h" -#include "thread.h" +#include "rl.h" #include "videodsp.h" #include "libavutil/opt.h" diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 9807e491e5..4ee7666c78 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -45,6 +45,7 @@ #include "encode.h" #include "idctdsp.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "mpegvideo.h" #include "mpegvideodata.h" #include "h261.h" diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 39b9f2e43a..c5dc867d24 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -22,6 +22,7 @@ #include "parser.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "internal.h" struct MpvParseContext { diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 4a2b422f13..8f8b791164 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -32,6 +32,7 @@ #include "avcodec.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "mpegvideo.h" #include "speedhqenc.h" From 8a431a2bb6295aab5517fb646e45b457a3d6de6c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 04:27:42 +0100 Subject: [PATCH 734/894] avcodec/mpegvideo_enc: Remove impossible branch Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 4ee7666c78..79f67ca01b 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3596,9 +3596,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, !!s->intra_penalty); } } - } - - if(s->pict_type==AV_PICTURE_TYPE_B){ + } else if (s->pict_type == AV_PICTURE_TYPE_B) { int a, b; a = ff_get_best_fcode(s, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); From 3ff94f88c2f4687a7b4aae05793cc2b6821c64f0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 15:09:55 +0100 Subject: [PATCH 735/894] avcodec/speedhqenc: Inline constants Signed-off-by: Andreas Rheinhardt --- libavcodec/speedhqenc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 8f8b791164..967774931c 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -213,8 +213,9 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[code][1] + 1, ff_rl_speedhq.table_vlc[code][0] + (sign << ff_rl_speedhq.table_vlc[code][1])); } else { - /* escape seems to be pretty rare <5% so I do not optimize it */ - put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[121][1], ff_rl_speedhq.table_vlc[121][0]); + /* escape seems to be pretty rare <5% so I do not optimize it; + * the values correspond to ff_rl_speedhq.table_vlc[121] */ + put_bits_le(&s->pb, 6, 32); /* escape: only clip in this case */ put_bits_le(&s->pb, 6, run); put_bits_le(&s->pb, 12, level + 2048); @@ -222,8 +223,8 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) last_non_zero = i; } } - /* end of block */ - put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[122][1], ff_rl_speedhq.table_vlc[122][0]); + /* end of block; the values correspond to ff_rl_speedhq.table_vlc[122] */ + put_bits_le(&s->pb, 4, 6); } void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) From 7a2f7283020a5723cf11b4fec6ceaa3470329601 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 16:49:57 +0100 Subject: [PATCH 736/894] avcodec/mpegvideo_enc: Move updating mb_info to its only user It is a H.263 option. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 79f67ca01b..0c98629603 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -2906,8 +2906,6 @@ static int encode_thread(AVCodecContext *c, void *arg){ } } - update_mb_info(s, 1); - switch(s->codec_id){ case AV_CODEC_ID_MPEG4: if (CONFIG_MPEG4_ENCODER) { @@ -2924,8 +2922,10 @@ static int encode_thread(AVCodecContext *c, void *arg){ break; case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: - if (CONFIG_H263_ENCODER) + if (CONFIG_H263_ENCODER) { + update_mb_info(s, 1); ff_h263_encode_gob_header(s, mb_y); + } break; } From ac49439e7734f384206b77ab6860d74f5969c281 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 17:10:12 +0100 Subject: [PATCH 737/894] avcodec/mpeg12enc: Simplify check for A53 closed captions The a53_cc option is only useful and meaningful for MPEG-2, yet it was accidentally added for all mpegvideo-based encoders. This means that it is possible for a53_cc to be set for other encoders as well. This commit changes this and reroutes a53_cc to the dummy field in MpegEncContext for all codecs for which it is not supported. This allows to avoid a check for the current codec in mpeg12enc.c. Also add a compile-time check for whether the MPEG-2 encoder is available while at it. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpegvideo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 2fb2232f3c..abb0a4b29f 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -551,7 +551,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) } } - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->a53_cc) { + if (CONFIG_MPEG2VIDEO_ENCODER && s->a53_cc) { side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC); if (side_data) { diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index d810f900f2..900b8b1403 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -662,7 +662,7 @@ FF_MPV_OPT_CMP_FUNC, \ #define FF_MPV_DEPRECATED_MPEG_QUANT_OPT \ { "mpeg_quant", "Deprecated, does nothing", FF_MPV_OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 0, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, #define FF_MPV_DEPRECATED_A53_CC_OPT \ - { "a53cc", "Deprecated, does nothing", FF_MPV_OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, + { "a53cc", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, #define FF_MPV_DEPRECATED_MATRIX_OPT \ { "force_duplicated_matrix", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, #define FF_MPV_DEPRECATED_BFRAME_OPTS \ From 4989ad4c76e2e74f7a1ff490ec9e33291de862fc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 17:28:20 +0100 Subject: [PATCH 738/894] avcodec/mpeg12enc: Add custom context, move mpeg2_frame_rate_ext to it It is only used here. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12enc.c | 26 +++++++++++++++++--------- libavcodec/mpegvideo.h | 1 - 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index abb0a4b29f..97df5523cc 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -62,6 +62,11 @@ static uint8_t uni_mpeg2_ac_vlc_len[64 * 64 * 2]; static uint32_t mpeg1_lum_dc_uni[512]; static uint32_t mpeg1_chr_dc_uni[512]; +typedef struct MPEG12EncContext { + MpegEncContext mpeg; + AVRational frame_rate_ext; +} MPEG12EncContext; + #define A53_MAX_CC_COUNT 0x1f #endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */ @@ -101,8 +106,9 @@ av_cold void ff_mpeg1_init_uni_ac_vlc(const RLTable *rl, uint8_t *uni_ac_vlc_len } #if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER -static int find_frame_rate_index(MpegEncContext *s) +static int find_frame_rate_index(MPEG12EncContext *mpeg12) { + MpegEncContext *const s = &mpeg12->mpeg; int i; AVRational bestq = (AVRational) {0, 0}; AVRational ext; @@ -127,8 +133,8 @@ static int find_frame_rate_index(MpegEncContext *s) || ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0) { bestq = q; s->frame_rate_index = i; - s->mpeg2_frame_rate_ext.num = ext.num; - s->mpeg2_frame_rate_ext.den = ext.den; + mpeg12->frame_rate_ext.num = ext.num; + mpeg12->frame_rate_ext.den = ext.den; } } } @@ -142,8 +148,9 @@ static int find_frame_rate_index(MpegEncContext *s) static av_cold int encode_init(AVCodecContext *avctx) { + MPEG12EncContext *const mpeg12 = avctx->priv_data; + MpegEncContext *const s = &mpeg12->mpeg; int ret; - MpegEncContext *s = avctx->priv_data; int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095; if (avctx->width > max_size || avctx->height > max_size) { @@ -199,7 +206,7 @@ static av_cold int encode_init(AVCodecContext *avctx) if ((ret = ff_mpv_encode_init(avctx)) < 0) return ret; - if (find_frame_rate_index(s) < 0) { + if (find_frame_rate_index(mpeg12) < 0) { if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num); @@ -244,6 +251,7 @@ static void put_header(MpegEncContext *s, int header) /* put sequence header if needed */ static void mpeg1_encode_sequence_header(MpegEncContext *s) { + MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; unsigned int vbv_buffer_size, fps, v; int i, constraint_parameter_flag; uint64_t time_code; @@ -339,8 +347,8 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_bits(&s->pb, 1, 1); // marker put_bits(&s->pb, 8, vbv_buffer_size >> 10); // vbv buffer ext put_bits(&s->pb, 1, s->low_delay); - put_bits(&s->pb, 2, s->mpeg2_frame_rate_ext.num-1); // frame_rate_ext_n - put_bits(&s->pb, 5, s->mpeg2_frame_rate_ext.den-1); // frame_rate_ext_d + put_bits(&s->pb, 2, mpeg12->frame_rate_ext.num-1); // frame_rate_ext_n + put_bits(&s->pb, 5, mpeg12->frame_rate_ext.den-1); // frame_rate_ext_d side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_PANSCAN); if (side_data) { @@ -1204,7 +1212,7 @@ const AVCodec ff_mpeg1video_encoder = { .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPEG12EncContext), .init = encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, @@ -1221,7 +1229,7 @@ const AVCodec ff_mpeg2video_encoder = { .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPEG12EncContext), .init = encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 900b8b1403..2611e7c667 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -203,7 +203,6 @@ typedef struct MpegEncContext { int last_non_b_pict_type; ///< used for MPEG-4 gmc B-frames & ratecontrol int droppable; int frame_rate_index; - AVRational mpeg2_frame_rate_ext; int last_lambda_for[5]; ///< last lambda for a specific pict type int skipdct; ///< skip dct and code zero residual From f899e3b51bc85c45f54f7ac64abfbde6b2cd7d3d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 22 Dec 2021 20:25:13 +0100 Subject: [PATCH 739/894] avcodec/mpeg12enc: Move options-related fields to MPEG12EncContext Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12dec.c | 1 + libavcodec/mpeg12enc.c | 58 +++++++++++++++++++++++++----------------- libavcodec/mpegvideo.h | 9 ------- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index cf06af0a71..797dd9ad3e 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -33,6 +33,7 @@ #include "libavutil/internal.h" #include "libavutil/mem_internal.h" #include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" #include "libavutil/video_enc_params.h" #include "avcodec.h" diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 97df5523cc..3692494713 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -65,6 +65,16 @@ static uint32_t mpeg1_chr_dc_uni[512]; typedef struct MPEG12EncContext { MpegEncContext mpeg; AVRational frame_rate_ext; + + int64_t timecode_frame_start; ///< GOP timecode frame start number, in non drop frame format + AVTimecode tc; ///< timecode context + char *tc_opt_str; ///< timecode option string + int drop_frame_timecode; ///< timecode is in drop frame format. + int scan_offset; ///< reserve space for SVCD scan offset user data. + + int a53_cc; + int seq_disp_ext; + int video_format; } MPEG12EncContext; #define A53_MAX_CC_COUNT 0x1f @@ -218,24 +228,24 @@ static av_cold int encode_init(AVCodecContext *avctx) } } - s->drop_frame_timecode = s->drop_frame_timecode || !!(avctx->flags2 & AV_CODEC_FLAG2_DROP_FRAME_TIMECODE); - if (s->drop_frame_timecode) - s->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; - if (s->drop_frame_timecode && s->frame_rate_index != 4) { + mpeg12->drop_frame_timecode = mpeg12->drop_frame_timecode || !!(avctx->flags2 & AV_CODEC_FLAG2_DROP_FRAME_TIMECODE); + if (mpeg12->drop_frame_timecode) + mpeg12->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; + if (mpeg12->drop_frame_timecode && s->frame_rate_index != 4) { av_log(avctx, AV_LOG_ERROR, "Drop frame time code only allowed with 1001/30000 fps\n"); return AVERROR(EINVAL); } - if (s->tc_opt_str) { + if (mpeg12->tc_opt_str) { AVRational rate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; - int ret = av_timecode_init_from_string(&s->tc, rate, s->tc_opt_str, s); + int ret = av_timecode_init_from_string(&mpeg12->tc, rate, mpeg12->tc_opt_str, s); if (ret < 0) return ret; - s->drop_frame_timecode = !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); - s->timecode_frame_start = s->tc.start; + mpeg12->drop_frame_timecode = !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); + mpeg12->timecode_frame_start = mpeg12->tc.start; } else { - s->timecode_frame_start = 0; // default is -1 + mpeg12->timecode_frame_start = 0; // default is -1 } return 0; @@ -364,12 +374,13 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) s->avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || s->avctx->color_trc != AVCOL_TRC_UNSPECIFIED || s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED || - s->video_format != VIDEO_FORMAT_UNSPECIFIED); + mpeg12->video_format != VIDEO_FORMAT_UNSPECIFIED); - if (s->seq_disp_ext == 1 || (s->seq_disp_ext == -1 && use_seq_disp_ext)) { + if (mpeg12->seq_disp_ext == 1 || + (mpeg12->seq_disp_ext == -1 && use_seq_disp_ext)) { put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 2); // sequence display extension - put_bits(&s->pb, 3, s->video_format); // video_format + put_bits(&s->pb, 3, mpeg12->video_format); // video_format put_bits(&s->pb, 1, 1); // colour_description put_bits(&s->pb, 8, s->avctx->color_primaries); // colour_primaries put_bits(&s->pb, 8, s->avctx->color_trc); // transfer_characteristics @@ -382,17 +393,17 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) } put_header(s, GOP_START_CODE); - put_bits(&s->pb, 1, s->drop_frame_timecode); // drop frame flag + put_bits(&s->pb, 1, mpeg12->drop_frame_timecode); // drop frame flag /* time code: we must convert from the real frame rate to a * fake MPEG frame rate in case of low frame rate */ fps = (framerate.num + framerate.den / 2) / framerate.den; time_code = s->current_picture_ptr->f->coded_picture_number + - s->timecode_frame_start; + mpeg12->timecode_frame_start; s->gop_picture_number = s->current_picture_ptr->f->coded_picture_number; - av_assert0(s->drop_frame_timecode == !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); - if (s->drop_frame_timecode) + av_assert0(mpeg12->drop_frame_timecode == !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); + if (mpeg12->drop_frame_timecode) time_code = av_timecode_adjust_ntsc_framenum2(time_code, fps); put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24)); @@ -436,6 +447,7 @@ void ff_mpeg1_encode_slice_header(MpegEncContext *s) void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) { + MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; AVFrameSideData *side_data; mpeg1_encode_sequence_header(s); @@ -513,7 +525,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) put_bits(&s->pb, 1, s->progressive_frame); put_bits(&s->pb, 1, 0); /* composite_display_flag */ } - if (s->scan_offset) { + if (mpeg12->scan_offset) { int i; put_header(s, USER_START_CODE); @@ -559,7 +571,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) } } - if (CONFIG_MPEG2VIDEO_ENCODER && s->a53_cc) { + if (CONFIG_MPEG2VIDEO_ENCODER && mpeg12->a53_cc) { side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC); if (side_data) { @@ -1138,7 +1150,7 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) ff_thread_once(&init_static_once, mpeg12_encode_init_static); } -#define OFFSET(x) offsetof(MpegEncContext, x) +#define OFFSET(x) offsetof(MPEG12EncContext, x) #define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM #define COMMON_OPTS \ { "gop_timecode", "MPEG GOP Timecode in hh:mm:ss[:;.]ff format. Overrides timecode_frame_start.", \ @@ -1165,9 +1177,9 @@ static const AVOption mpeg1_options[] = { static const AVOption mpeg2_options[] = { COMMON_OPTS { "intra_vlc", "Use MPEG-2 intra VLC table.", - OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "non_linear_quant", "Use nonlinear quantizer.", OFFSET(q_scale_type), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + FF_MPV_OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "non_linear_quant", "Use nonlinear quantizer.", FF_MPV_OFFSET(q_scale_type), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "alternate_scan", "Enable alternate scantable.", FF_MPV_OFFSET(alternate_scan), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, { "seq_disp_ext", "Write sequence_display_extension blocks.", OFFSET(seq_disp_ext), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "seq_disp_ext" }, { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "seq_disp_ext" }, @@ -1188,7 +1200,7 @@ static const AVOption mpeg2_options[] = { #undef LEVEL FF_MPV_COMMON_OPTS #if FF_API_MPEGVIDEO_OPTS - { "mpeg_quant", "Deprecated, does nothing", OFFSET(mpeg_quant), + { "mpeg_quant", "Deprecated, does nothing", FF_MPV_OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED }, FF_MPV_DEPRECATED_MATRIX_OPT #endif diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 2611e7c667..fabcce2436 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -58,7 +58,6 @@ #include "videodsp.h" #include "libavutil/opt.h" -#include "libavutil/timecode.h" #define MAX_THREADS 32 @@ -443,7 +442,6 @@ typedef struct MpegEncContext { /* MPEG-2-specific - I wished not to have to support this mess. */ int progressive_sequence; int mpeg_f_code[2][2]; - int a53_cc; // picture structure defines are loaded from mpegutils.h int picture_structure; @@ -457,8 +455,6 @@ typedef struct MpegEncContext { int brd_scale; int intra_vlc_format; int alternate_scan; - int seq_disp_ext; - int video_format; #define VIDEO_FORMAT_COMPONENT 0 #define VIDEO_FORMAT_PAL 1 #define VIDEO_FORMAT_NTSC 2 @@ -478,16 +474,11 @@ typedef struct MpegEncContext { int full_pel[2]; int interlaced_dct; int first_field; ///< is 1 for the first field of a field picture 0 otherwise - int drop_frame_timecode; ///< timecode is in drop frame format. - int scan_offset; ///< reserve space for SVCD scan offset user data. /* RTP specific */ int rtp_mode; int rtp_payload_size; - char *tc_opt_str; ///< timecode option string - AVTimecode tc; ///< timecode context - uint8_t *ptr_lastgob; int swap_uv; //vcr2 codec is an MPEG-2 variant with U and V swapped int pack_pblocks; //xvmc needs to keep blocks without gaps. From 2d2aa5c38443b9d6b4767679913f0964c32a28f9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 00:41:18 +0100 Subject: [PATCH 740/894] avcodec/mpegvideo_enc: Don't merge decoder-only fields Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 0c98629603..0279816d3c 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3404,8 +3404,6 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) MERGE(b_count); MERGE(skip_count); MERGE(misc_bits); - MERGE(er.error_count); - MERGE(padding_bug_score); MERGE(current_picture.encoding_error[0]); MERGE(current_picture.encoding_error[1]); MERGE(current_picture.encoding_error[2]); From ec5c188b21cb9475b6b8536b3f1f4e32889feeee Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 01:27:59 +0100 Subject: [PATCH 741/894] avcodec/mpeg12dec: Use %c to write single char Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12dec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 797dd9ad3e..35dfc74fe7 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1790,13 +1790,13 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, if (s->mb_y == 0 && s->mb_x == 0 && (s->first_field || s->picture_structure == PICT_FRAME)) { if (s->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(s->avctx, AV_LOG_DEBUG, - "qp:%d fc:%2d%2d%2d%2d %s %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", + "qp:%d fc:%2d%2d%2d%2d %c %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", s->qscale, s->mpeg_f_code[0][0], s->mpeg_f_code[0][1], s->mpeg_f_code[1][0], s->mpeg_f_code[1][1], - s->pict_type == AV_PICTURE_TYPE_I ? "I" : - (s->pict_type == AV_PICTURE_TYPE_P ? "P" : - (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + s->pict_type == AV_PICTURE_TYPE_I ? 'I' : + (s->pict_type == AV_PICTURE_TYPE_P ? 'P' : + (s->pict_type == AV_PICTURE_TYPE_B ? 'B' : 'S')), s->progressive_sequence ? "ps" : "", s->progressive_frame ? "pf" : "", s->alternate_scan ? "alt" : "", From 5d856ef476f0fdb06e54c71c43a79d26b3d213f9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 03:19:20 +0100 Subject: [PATCH 742/894] avcodec/mpegvideo: Don't duplicate identical code Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 657970a450..a0d05f8b46 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1963,25 +1963,6 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], { const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; - if (CONFIG_XVMC && - s->avctx->hwaccel && s->avctx->hwaccel->decode_mb) { - s->avctx->hwaccel->decode_mb(s);//xvmc uses pblocks - return; - } - - if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { - /* print DCT coefficients */ - int i,j; - av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); - for(i=0; i<6; i++){ - for(j=0; j<64; j++){ - av_log(s->avctx, AV_LOG_DEBUG, "%5d", - block[i][s->idsp.idct_permutation[j]]); - } - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - } - s->current_picture.qscale_table[mb_xy] = s->qscale; /* update DC predictors for P macroblocks */ @@ -2263,6 +2244,24 @@ skip_idct: void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]) { + if (CONFIG_XVMC && + s->avctx->hwaccel && s->avctx->hwaccel->decode_mb) { + s->avctx->hwaccel->decode_mb(s); //xvmc uses pblocks + return; + } + + if (s->avctx->debug & FF_DEBUG_DCT_COEFF) { + /* print DCT coefficients */ + av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 64; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "%5d", + block[i][s->idsp.idct_permutation[j]]); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + } + #if !CONFIG_SMALL if(s->out_format == FMT_MPEG1) { if(s->avctx->lowres) mpv_reconstruct_mb_internal(s, block, 1, 1); From 22ef01f5e142ffc38d4365b284cba5747a2d9982 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 03:37:12 +0100 Subject: [PATCH 743/894] avcodec/mpegvideo: Avoid needlessly calling function The very first check in this if-else if-else if construct is "if (s->encoding ||", i.e. in case of the WMV2 encoder the else branches are never executed. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index a0d05f8b46..5e87a41f52 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2122,8 +2122,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } } }//fi gray - } - else if (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) { + } else if (CONFIG_WMV2_DECODER) { ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr); } } else { From b821a58741fddce0e103b2d9a93c313904241003 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 03:57:55 +0100 Subject: [PATCH 744/894] avcodec/wmv2: Move ff_wmv2_add_mb() to the wmv2dec Only the decoder ever used it. Signed-off-by: Andreas Rheinhardt --- libavcodec/wmv2.c | 44 -------------------------------------------- libavcodec/wmv2dec.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index 327c5bdae1..fd64a0938f 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -23,7 +23,6 @@ #include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4data.h" -#include "simple_idct.h" #include "wmv2.h" #include "wmv2data.h" @@ -54,49 +53,6 @@ av_cold void ff_wmv2_common_init(Wmv2Context *w) s->idsp.idct = NULL; } -static void wmv2_add_block(Wmv2Context *w, int16_t *block1, - uint8_t *dst, int stride, int n) -{ - MpegEncContext *const s = &w->s; - - if (s->block_last_index[n] >= 0) { - switch (w->abt_type_table[n]) { - case 0: - w->wdsp.idct_add(dst, stride, block1); - break; - case 1: - ff_simple_idct84_add(dst, stride, block1); - ff_simple_idct84_add(dst + 4 * stride, stride, w->abt_block2[n]); - s->bdsp.clear_block(w->abt_block2[n]); - break; - case 2: - ff_simple_idct48_add(dst, stride, block1); - ff_simple_idct48_add(dst + 4, stride, w->abt_block2[n]); - s->bdsp.clear_block(w->abt_block2[n]); - break; - default: - av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); - } - } -} - -void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], - uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr) -{ - Wmv2Context *const w = (Wmv2Context *) s; - - wmv2_add_block(w, block1[0], dest_y, s->linesize, 0); - wmv2_add_block(w, block1[1], dest_y + 8, s->linesize, 1); - wmv2_add_block(w, block1[2], dest_y + 8 * s->linesize, s->linesize, 2); - wmv2_add_block(w, block1[3], dest_y + 8 + 8 * s->linesize, s->linesize, 3); - - if (s->avctx->flags & AV_CODEC_FLAG_GRAY) - return; - - wmv2_add_block(w, block1[4], dest_cb, s->uvlinesize, 4); - wmv2_add_block(w, block1[5], dest_cr, s->uvlinesize, 5); -} - void ff_mspel_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, uint8_t **ref_picture, op_pixels_func (*pix_op)[4], diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index c500e3e779..f7745c5a83 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -27,9 +27,53 @@ #include "mpegvideo.h" #include "msmpeg4.h" #include "msmpeg4data.h" +#include "simple_idct.h" #include "wmv2.h" +static void wmv2_add_block(Wmv2Context *w, int16_t *block1, + uint8_t *dst, int stride, int n) +{ + MpegEncContext *const s = &w->s; + + if (s->block_last_index[n] >= 0) { + switch (w->abt_type_table[n]) { + case 0: + w->wdsp.idct_add(dst, stride, block1); + break; + case 1: + ff_simple_idct84_add(dst, stride, block1); + ff_simple_idct84_add(dst + 4 * stride, stride, w->abt_block2[n]); + s->bdsp.clear_block(w->abt_block2[n]); + break; + case 2: + ff_simple_idct48_add(dst, stride, block1); + ff_simple_idct48_add(dst + 4, stride, w->abt_block2[n]); + s->bdsp.clear_block(w->abt_block2[n]); + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); + } + } +} + +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr) +{ + Wmv2Context *const w = (Wmv2Context *) s; + + wmv2_add_block(w, block1[0], dest_y, s->linesize, 0); + wmv2_add_block(w, block1[1], dest_y + 8, s->linesize, 1); + wmv2_add_block(w, block1[2], dest_y + 8 * s->linesize, s->linesize, 2); + wmv2_add_block(w, block1[3], dest_y + 8 + 8 * s->linesize, s->linesize, 3); + + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; + + wmv2_add_block(w, block1[4], dest_cb, s->uvlinesize, 4); + wmv2_add_block(w, block1[5], dest_cr, s->uvlinesize, 5); +} + static int parse_mb_skip(Wmv2Context *w) { int mb_x, mb_y; From f5ddf0ab197cb88bac3ce361481a0408f5fd8ea7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 04:03:46 +0100 Subject: [PATCH 745/894] avcodec/mpegvideo_motion: Don't duplicate identical code Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_motion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index 427bc96887..876a7375f8 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -839,8 +839,6 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s, int i; int mb_y = s->mb_y; - prefetch_motion(s, ref_picture, dir); - if (!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B) { apply_obmc(s, dest_y, dest_cb, dest_cr, ref_picture, pix_op); return; @@ -978,6 +976,8 @@ void ff_mpv_motion(MpegEncContext *s, op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16]) { + prefetch_motion(s, ref_picture, dir); + #if !CONFIG_SMALL if (s->out_format == FMT_MPEG1) mpv_motion_internal(s, dest_y, dest_cb, dest_cr, dir, From 854e3d47341b7c551c68abd6e19bbe6c20c6040b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 04:42:51 +0100 Subject: [PATCH 746/894] avcodec/mpegvideo: Don't check for > 8 bit MPEG-1/2 It doesn't exist. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 5e87a41f52..b38282dcb2 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2128,7 +2128,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } else { /* Only MPEG-4 Simple Studio Profile is supported in > 8-bit mode. TODO: Integrate 10-bit properly into mpegvideo.c so that ER works properly */ - if (s->avctx->bits_per_raw_sample > 8){ + if (!is_mpeg12 && s->avctx->bits_per_raw_sample > 8) { const int act_block_size = block_size * 2; if(s->dpcm_direction == 0) { From 7c0c73bca0bc73fbb7f02128bd6b2af95f3ceb38 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 05:43:33 +0100 Subject: [PATCH 747/894] avcodec/mpegvideo: Partially check for being encoder at compile-time Whether lowres is in use or not is inlined in mpv_reconstruct_mb_internal(), so one can use the fact that lowres is always zero during encoding to evaluate the checks for whether one is encoding or not at compile-time when one is in lowres mode. Also reorder the main check to check for whether it is an encoder first to shortcircuit it in the common case of a decoder. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index b38282dcb2..0d09a3f058 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1961,6 +1961,7 @@ static av_always_inline void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], int lowres_flag, int is_mpeg12) { +#define IS_ENCODER(s) (CONFIG_MPEGVIDEOENC && !lowres_flag && (s)->encoding) const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; s->current_picture.qscale_table[mb_xy] = s->qscale; @@ -1979,8 +1980,8 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], else if (!is_mpeg12 && (s->h263_pred || s->h263_aic)) s->mbintra_table[mb_xy]=1; - if ((s->avctx->flags & AV_CODEC_FLAG_PSNR) || s->frame_skip_threshold || s->frame_skip_factor || - !(s->encoding && (s->intra_only || s->pict_type == AV_PICTURE_TYPE_B) && + if (!IS_ENCODER(s) || (s->avctx->flags & AV_CODEC_FLAG_PSNR) || s->frame_skip_threshold || s->frame_skip_factor || + !((s->intra_only || s->pict_type == AV_PICTURE_TYPE_B) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { // FIXME precalc uint8_t *dest_y, *dest_cb, *dest_cr; int dct_linesize, dct_offset; @@ -1988,12 +1989,12 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], qpel_mc_func (*op_qpix)[16]; const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics const int uvlinesize = s->current_picture.f->linesize[1]; - const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band || lowres_flag; + const int readable = s->pict_type != AV_PICTURE_TYPE_B || IS_ENCODER(s) || s->avctx->draw_horiz_band || lowres_flag; const int block_size= lowres_flag ? 8>>s->avctx->lowres : 8; /* avoid copy if macroblock skipped in last frame too */ /* skip only during decoding as we might trash the buffers during encoding a bit */ - if(!s->encoding){ + if (!IS_ENCODER(s)) { uint8_t *mbskip_ptr = &s->mbskip_table[mb_xy]; if (s->mb_skipped) { @@ -2023,7 +2024,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], if (!s->mb_intra) { /* motion handling */ /* decoding or more than one mb_type (MC was already done otherwise) */ - if(!s->encoding){ + if (!IS_ENCODER(s)) { if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { if (s->mv_dir & MV_DIR_FORWARD) { @@ -2075,7 +2076,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } /* add dct residue */ - if(s->encoding || !( s->msmpeg4_version || s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO + if (IS_ENCODER(s) || !(s->msmpeg4_version || s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || (s->codec_id==AV_CODEC_ID_MPEG4 && !s->mpeg_quant))){ add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); @@ -2182,7 +2183,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } } /* dct only in intra block */ - else if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ + else if (IS_ENCODER(s) || !(s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO)) { put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); From bf70c34b117c9c4a4885089e053ff59c93a6c5f3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 06:34:24 +0100 Subject: [PATCH 748/894] avcodec/mpegvideo: Try to perform check for MPEG-1/2 at compile-time This is possible if CONFIG_SMALL is not true. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 0d09a3f058..28e69ea113 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1962,6 +1962,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], int lowres_flag, int is_mpeg12) { #define IS_ENCODER(s) (CONFIG_MPEGVIDEOENC && !lowres_flag && (s)->encoding) +#define IS_MPEG12(s) (CONFIG_SMALL ? ((s)->out_format == FMT_MPEG1) : is_mpeg12) const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; s->current_picture.qscale_table[mb_xy] = s->qscale; @@ -2076,7 +2077,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } /* add dct residue */ - if (IS_ENCODER(s) || !(s->msmpeg4_version || s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO + if (IS_ENCODER(s) || !(IS_MPEG12(s) || s->msmpeg4_version || (s->codec_id==AV_CODEC_ID_MPEG4 && !s->mpeg_quant))){ add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); @@ -2183,7 +2184,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } } /* dct only in intra block */ - else if (IS_ENCODER(s) || !(s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO)) { + else if (IS_ENCODER(s) || !IS_MPEG12(s)) { put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); From 7d4f200dfa1df80809eec75b0d96bc97475bd01d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 07:12:17 +0100 Subject: [PATCH 749/894] avcodec/mpegvideo: Remove always-true branch Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 28e69ea113..01b184bbd7 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2166,10 +2166,11 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], dest_pcm[i] += linesize[i] / 2; } } - } else if(s->dpcm_direction == -1) { + } else { int i, w, h; uint16_t *dest_pcm[3] = {(uint16_t*)dest_y, (uint16_t*)dest_cb, (uint16_t*)dest_cr}; int linesize[3] = {dct_linesize, uvlinesize, uvlinesize}; + av_assert2(s->dpcm_direction == -1); for(i = 0; i < 3; i++) { int idx = 0; int vsub = i ? s->chroma_y_shift : 0; From 4a9b460a096f7225856550c2eb3a41402b7b812d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 07:19:36 +0100 Subject: [PATCH 750/894] avcodec/mpegvideo: Check for no_rounding at compile-time if possible It is partially possible if it is inlined whether we deal with MPEG-1/2, because no_rounding is never set for MPEG-1/2. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 01b184bbd7..f2618f5b7b 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2052,7 +2052,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } }else{ op_qpix = s->me.qpel_put; - if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){ + if ((is_mpeg12 || !s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { op_pix = s->hdsp.put_pixels_tab; }else{ op_pix = s->hdsp.put_no_rnd_pixels_tab; From 5de7bce12e9469911a743cb3dcfb86776ccbf57c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 22:29:03 +0100 Subject: [PATCH 751/894] avcodec/mpegvideo: Don't initialize error resilience context for encoder It is only used for decoders. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index f2618f5b7b..129e0ef647 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -835,7 +835,7 @@ static int init_context_frame(MpegEncContext *s) return AVERROR(ENOMEM); memset(s->mbintra_table, 1, mb_array_size); - return ff_mpeg_er_init(s); + return s->encoding ? 0 : ff_mpeg_er_init(s); } static void clear_context(MpegEncContext *s) From ee41c60373fcb8b1d49929367e564020361838da Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 23 Dec 2021 22:56:11 +0100 Subject: [PATCH 752/894] avcodec/mpegvideo: Remove always-false check An AVCodecContext's private data is always allocated in avcodec_open2() and calling avcodec_flush_buffers() on an unopened AVCodecContext (or an already closed one) is not allowed (and will crash before the decoder's flush function is even called). Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 129e0ef647..d34dadf939 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2318,7 +2318,7 @@ void ff_mpeg_flush(AVCodecContext *avctx){ int i; MpegEncContext *s = avctx->priv_data; - if (!s || !s->picture) + if (!s->picture) return; for (i = 0; i < MAX_PICTURE_COUNT; i++) From d83479bec1683f886d45906d155ab84bc4aebeda Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 24 Dec 2021 00:23:00 +0100 Subject: [PATCH 753/894] avcodec/mpegvideo: Move decoding-only code into a new file This will allow to disable this code altogether when all decoders are disabled. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 2 +- libavcodec/mpegvideo.c | 582 +----------------------------------- libavcodec/mpegvideo.h | 22 ++ libavcodec/mpegvideo_dec.c | 583 +++++++++++++++++++++++++++++++++++++ 4 files changed, 612 insertions(+), 577 deletions(-) create mode 100644 libavcodec/mpegvideo_dec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 81a11a3688..fc07308615 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -125,7 +125,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_float.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o -OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ +OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideo_dec.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ mpegvideodata.o mpegpicture.o \ to_upper4.o diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index d34dadf939..a2c4e14b6e 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -31,13 +31,11 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" -#include "libavutil/video_enc_params.h" #include "avcodec.h" #include "blockdsp.h" #include "h264chroma.h" #include "idctdsp.h" -#include "internal.h" #include "mathops.h" #include "mpeg_er.h" #include "mpegutils.h" @@ -345,14 +343,6 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s) ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } -static int alloc_picture(MpegEncContext *s, Picture *pic) -{ - return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, 0, 0, - s->chroma_x_shift, s->chroma_y_shift, s->out_format, - s->mb_stride, s->mb_width, s->mb_height, s->b8_stride, - &s->linesize, &s->uvlinesize); -} - static int init_duplicate_context(MpegEncContext *s) { int y_size = s->b8_stride * (2 * s->mb_height + 1); @@ -403,12 +393,7 @@ static int init_duplicate_context(MpegEncContext *s) return 0; } -/** - * Initialize an MpegEncContext's thread contexts. Presumes that - * slice_context_count is already set and that all the fields - * that are freed/reset in free_duplicate_context() are NULL. - */ -static int init_duplicate_contexts(MpegEncContext *s) +int ff_mpv_init_duplicate_contexts(MpegEncContext *s) { int nb_slices = s->slice_context_count, ret; @@ -518,146 +503,6 @@ int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) return 0; } -int ff_mpeg_update_thread_context(AVCodecContext *dst, - const AVCodecContext *src) -{ - int i, ret; - MpegEncContext *s = dst->priv_data, *s1 = src->priv_data; - - if (dst == src) - return 0; - - av_assert0(s != s1); - - // FIXME can parameters change on I-frames? - // in that case dst may need a reinit - if (!s->context_initialized) { - int err; - memcpy(s, s1, sizeof(MpegEncContext)); - - s->avctx = dst; - s->bitstream_buffer = NULL; - s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; - - if (s1->context_initialized){ -// s->picture_range_start += MAX_PICTURE_COUNT; -// s->picture_range_end += MAX_PICTURE_COUNT; - ff_mpv_idct_init(s); - if((err = ff_mpv_common_init(s)) < 0){ - memset(s, 0, sizeof(MpegEncContext)); - s->avctx = dst; - return err; - } - } - } - - if (s->height != s1->height || s->width != s1->width || s->context_reinit) { - s->height = s1->height; - s->width = s1->width; - if ((ret = ff_mpv_common_frame_size_change(s)) < 0) - return ret; - } - - s->avctx->coded_height = s1->avctx->coded_height; - s->avctx->coded_width = s1->avctx->coded_width; - s->avctx->width = s1->avctx->width; - s->avctx->height = s1->avctx->height; - - s->quarter_sample = s1->quarter_sample; - - s->coded_picture_number = s1->coded_picture_number; - s->picture_number = s1->picture_number; - - av_assert0(!s->picture || s->picture != s1->picture); - if(s->picture) - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - if (s1->picture && s1->picture[i].f->buf[0] && - (ret = ff_mpeg_ref_picture(s->avctx, &s->picture[i], &s1->picture[i])) < 0) - return ret; - } - -#define UPDATE_PICTURE(pic)\ -do {\ - ff_mpeg_unref_picture(s->avctx, &s->pic);\ - if (s1->pic.f && s1->pic.f->buf[0])\ - ret = ff_mpeg_ref_picture(s->avctx, &s->pic, &s1->pic);\ - else\ - ret = ff_update_picture_tables(&s->pic, &s1->pic);\ - if (ret < 0)\ - return ret;\ -} while (0) - - UPDATE_PICTURE(current_picture); - UPDATE_PICTURE(last_picture); - UPDATE_PICTURE(next_picture); - -#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ - ((pic && pic >= old_ctx->picture && \ - pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ - &new_ctx->picture[pic - old_ctx->picture] : NULL) - - s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); - s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); - s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); - - // Error/bug resilience - s->next_p_frame_damaged = s1->next_p_frame_damaged; - s->workaround_bugs = s1->workaround_bugs; - s->padding_bug_score = s1->padding_bug_score; - - // MPEG-4 timing info - memcpy(&s->last_time_base, &s1->last_time_base, - (char *) &s1->pb_field_time + sizeof(s1->pb_field_time) - - (char *) &s1->last_time_base); - - // B-frame info - s->max_b_frames = s1->max_b_frames; - s->low_delay = s1->low_delay; - s->droppable = s1->droppable; - - // DivX handling (doesn't work) - s->divx_packed = s1->divx_packed; - - if (s1->bitstream_buffer) { - if (s1->bitstream_buffer_size + - AV_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) { - av_fast_malloc(&s->bitstream_buffer, - &s->allocated_bitstream_buffer_size, - s1->allocated_bitstream_buffer_size); - if (!s->bitstream_buffer) { - s->bitstream_buffer_size = 0; - return AVERROR(ENOMEM); - } - } - s->bitstream_buffer_size = s1->bitstream_buffer_size; - memcpy(s->bitstream_buffer, s1->bitstream_buffer, - s1->bitstream_buffer_size); - memset(s->bitstream_buffer + s->bitstream_buffer_size, 0, - AV_INPUT_BUFFER_PADDING_SIZE); - } - - // linesize-dependent scratch buffer allocation - if (!s->sc.edge_emu_buffer) - if (s1->linesize) { - if (ff_mpeg_framesize_alloc(s->avctx, &s->me, - &s->sc, s1->linesize) < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " - "scratch buffers.\n"); - return AVERROR(ENOMEM); - } - } else { - av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " - "be allocated due to unknown size.\n"); - } - - // MPEG-2/interlacing info - memcpy(&s->progressive_sequence, &s1->progressive_sequence, - (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); - - return 0; -} - /** * Set the given MpegEncContext to common defaults * (same for encoding and decoding). @@ -682,29 +527,7 @@ void ff_mpv_common_defaults(MpegEncContext *s) s->slice_context_count = 1; } -/** - * Initialize the given MpegEncContext for decoding. - * the changed fields will not depend upon - * the prior state of the MpegEncContext. - */ -void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) -{ - ff_mpv_common_defaults(s); - - s->avctx = avctx; - s->width = avctx->coded_width; - s->height = avctx->coded_height; - s->codec_id = avctx->codec->id; - s->workaround_bugs = avctx->workaround_bugs; - - /* convert fourcc to upper case */ - s->codec_tag = ff_toupper4(avctx->codec_tag); -} - -/** - * Initialize and allocates MpegEncContext fields dependent on the resolution. - */ -static int init_context_frame(MpegEncContext *s) +int ff_mpv_init_context_frame(MpegEncContext *s) { int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; @@ -981,7 +804,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) !(s->new_picture.f = av_frame_alloc())) goto fail_nomem; - if ((ret = init_context_frame(s))) + if ((ret = ff_mpv_init_context_frame(s))) goto fail; #if FF_API_FLAG_TRUNCATED @@ -994,7 +817,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) s->slice_context_count = nb_slices; // if (s->width && s->height) { - ret = init_duplicate_contexts(s); + ret = ff_mpv_init_duplicate_contexts(s); if (ret < 0) goto fail; // } @@ -1007,13 +830,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) return ret; } -/** - * Frees and resets MpegEncContext fields depending on the resolution - * as well as the slice thread contexts. - * Is used during resolution changes to avoid a full reinitialization of the - * codec. - */ -static void free_context_frame(MpegEncContext *s) +void ff_mpv_free_context_frame(MpegEncContext *s) { int i, j, k; @@ -1066,61 +883,6 @@ static void free_context_frame(MpegEncContext *s) s->linesize = s->uvlinesize = 0; } -int ff_mpv_common_frame_size_change(MpegEncContext *s) -{ - int i, err = 0; - - if (!s->context_initialized) - return AVERROR(EINVAL); - - free_context_frame(s); - - if (s->picture) - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - s->picture[i].needs_realloc = 1; - } - - s->last_picture_ptr = - s->next_picture_ptr = - s->current_picture_ptr = NULL; - - // init - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) - s->mb_height = (s->height + 31) / 32 * 2; - else - s->mb_height = (s->height + 15) / 16; - - if ((s->width || s->height) && - (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0) - goto fail; - - /* set chroma shifts */ - err = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, - &s->chroma_x_shift, - &s->chroma_y_shift); - if (err < 0) - goto fail; - - if ((err = init_context_frame(s))) - goto fail; - - memset(s->thread_context, 0, sizeof(s->thread_context)); - s->thread_context[0] = s; - - if (s->width && s->height) { - err = init_duplicate_contexts(s); - if (err < 0) - goto fail; - } - s->context_reinit = 0; - - return 0; - fail: - free_context_frame(s); - s->context_reinit = 1; - return err; -} - /* init common structure for both encoder and decoder */ void ff_mpv_common_end(MpegEncContext *s) { @@ -1129,7 +891,7 @@ void ff_mpv_common_end(MpegEncContext *s) if (!s) return; - free_context_frame(s); + ff_mpv_free_context_frame(s); if (s->slice_context_count > 1) s->slice_context_count = 1; @@ -1174,296 +936,6 @@ void ff_mpv_common_end(MpegEncContext *s) } -static void gray_frame(AVFrame *frame) -{ - int i, h_chroma_shift, v_chroma_shift; - - av_pix_fmt_get_chroma_sub_sample(frame->format, &h_chroma_shift, &v_chroma_shift); - - for(i=0; iheight; i++) - memset(frame->data[0] + frame->linesize[0]*i, 0x80, frame->width); - for(i=0; iheight, v_chroma_shift); i++) { - memset(frame->data[1] + frame->linesize[1]*i, - 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); - memset(frame->data[2] + frame->linesize[2]*i, - 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); - } -} - -/** - * generic function called after decoding - * the header and before a frame is decoded. - */ -int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) -{ - int i, ret; - Picture *pic; - s->mb_skipped = 0; - - if (!ff_thread_can_start_frame(avctx)) { - av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); - return -1; - } - - /* mark & release old frames */ - if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && - s->last_picture_ptr != s->next_picture_ptr && - s->last_picture_ptr->f->buf[0]) { - ff_mpeg_unref_picture(s->avctx, s->last_picture_ptr); - } - - /* release forgotten pictures */ - /* if (MPEG-124 / H.263) */ - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (&s->picture[i] != s->last_picture_ptr && - &s->picture[i] != s->next_picture_ptr && - s->picture[i].reference && !s->picture[i].needs_realloc) { - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - } - } - - ff_mpeg_unref_picture(s->avctx, &s->current_picture); - ff_mpeg_unref_picture(s->avctx, &s->last_picture); - ff_mpeg_unref_picture(s->avctx, &s->next_picture); - - /* release non reference frames */ - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (!s->picture[i].reference) - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - } - - if (s->current_picture_ptr && !s->current_picture_ptr->f->buf[0]) { - // we already have an unused image - // (maybe it was set before reading the header) - pic = s->current_picture_ptr; - } else { - i = ff_find_unused_picture(s->avctx, s->picture, 0); - if (i < 0) { - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - pic = &s->picture[i]; - } - - pic->reference = 0; - if (!s->droppable) { - if (s->pict_type != AV_PICTURE_TYPE_B) - pic->reference = 3; - } - - pic->f->coded_picture_number = s->coded_picture_number++; - - if (alloc_picture(s, pic) < 0) - return -1; - - s->current_picture_ptr = pic; - // FIXME use only the vars from current_pic - s->current_picture_ptr->f->top_field_first = s->top_field_first; - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || - s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - if (s->picture_structure != PICT_FRAME) - s->current_picture_ptr->f->top_field_first = - (s->picture_structure == PICT_TOP_FIELD) == s->first_field; - } - s->current_picture_ptr->f->interlaced_frame = !s->progressive_frame && - !s->progressive_sequence; - s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; - - s->current_picture_ptr->f->pict_type = s->pict_type; - // if (s->avctx->flags && AV_CODEC_FLAG_QSCALE) - // s->current_picture_ptr->quality = s->new_picture_ptr->quality; - s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; - - if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, - s->current_picture_ptr)) < 0) - return ret; - - if (s->pict_type != AV_PICTURE_TYPE_B) { - s->last_picture_ptr = s->next_picture_ptr; - if (!s->droppable) - s->next_picture_ptr = s->current_picture_ptr; - } - ff_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", - s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, - s->last_picture_ptr ? s->last_picture_ptr->f->data[0] : NULL, - s->next_picture_ptr ? s->next_picture_ptr->f->data[0] : NULL, - s->current_picture_ptr ? s->current_picture_ptr->f->data[0] : NULL, - s->pict_type, s->droppable); - - if ((!s->last_picture_ptr || !s->last_picture_ptr->f->buf[0]) && - (s->pict_type != AV_PICTURE_TYPE_I)) { - int h_chroma_shift, v_chroma_shift; - av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, - &h_chroma_shift, &v_chroma_shift); - if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0]) - av_log(avctx, AV_LOG_DEBUG, - "allocating dummy last picture for B frame\n"); - else if (s->pict_type != AV_PICTURE_TYPE_I) - av_log(avctx, AV_LOG_ERROR, - "warning: first frame is no keyframe\n"); - - /* Allocate a dummy frame */ - i = ff_find_unused_picture(s->avctx, s->picture, 0); - if (i < 0) { - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - s->last_picture_ptr = &s->picture[i]; - - s->last_picture_ptr->reference = 3; - s->last_picture_ptr->f->key_frame = 0; - s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; - - if (alloc_picture(s, s->last_picture_ptr) < 0) { - s->last_picture_ptr = NULL; - return -1; - } - - if (!avctx->hwaccel) { - for(i=0; iheight; i++) - memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, - 0x80, avctx->width); - if (s->last_picture_ptr->f->data[2]) { - for(i=0; iheight, v_chroma_shift); i++) { - memset(s->last_picture_ptr->f->data[1] + s->last_picture_ptr->f->linesize[1]*i, - 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); - memset(s->last_picture_ptr->f->data[2] + s->last_picture_ptr->f->linesize[2]*i, - 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); - } - } - - if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){ - for(i=0; iheight; i++) - memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, 16, avctx->width); - } - } - - ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); - } - if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) && - s->pict_type == AV_PICTURE_TYPE_B) { - /* Allocate a dummy frame */ - i = ff_find_unused_picture(s->avctx, s->picture, 0); - if (i < 0) { - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - s->next_picture_ptr = &s->picture[i]; - - s->next_picture_ptr->reference = 3; - s->next_picture_ptr->f->key_frame = 0; - s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; - - if (alloc_picture(s, s->next_picture_ptr) < 0) { - s->next_picture_ptr = NULL; - return -1; - } - ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 1); - } - -#if 0 // BUFREF-FIXME - memset(s->last_picture.f->data, 0, sizeof(s->last_picture.f->data)); - memset(s->next_picture.f->data, 0, sizeof(s->next_picture.f->data)); -#endif - if (s->last_picture_ptr) { - if (s->last_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture, - s->last_picture_ptr)) < 0) - return ret; - } - if (s->next_picture_ptr) { - if (s->next_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture, - s->next_picture_ptr)) < 0) - return ret; - } - - av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && - s->last_picture_ptr->f->buf[0])); - - if (s->picture_structure!= PICT_FRAME) { - int i; - for (i = 0; i < 4; i++) { - if (s->picture_structure == PICT_BOTTOM_FIELD) { - s->current_picture.f->data[i] += - s->current_picture.f->linesize[i]; - } - s->current_picture.f->linesize[i] *= 2; - s->last_picture.f->linesize[i] *= 2; - s->next_picture.f->linesize[i] *= 2; - } - } - - /* set dequantizer, we can't do it during init as - * it might change for MPEG-4 and we can't do it in the header - * decode as init is not called for MPEG-4 there yet */ - if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; - s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; - } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { - s->dct_unquantize_intra = s->dct_unquantize_h263_intra; - s->dct_unquantize_inter = s->dct_unquantize_h263_inter; - } else { - s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra; - s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; - } - - if (s->avctx->debug & FF_DEBUG_NOMC) { - gray_frame(s->current_picture_ptr->f); - } - - return 0; -} - -/* called after a frame has been decoded. */ -void ff_mpv_frame_end(MpegEncContext *s) -{ - emms_c(); - - if (s->current_picture.reference) - ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); -} - -void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) -{ - ff_print_debug_info2(s->avctx, pict, s->mbskip_table, p->mb_type, - p->qscale_table, p->motion_val, - s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample); -} - -int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type) -{ - AVVideoEncParams *par; - int mult = (qp_type == FF_QSCALE_TYPE_MPEG1) ? 2 : 1; - unsigned int nb_mb = p->alloc_mb_height * p->alloc_mb_width; - unsigned int x, y; - - if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS)) - return 0; - - par = av_video_enc_params_create_side_data(f, AV_VIDEO_ENC_PARAMS_MPEG2, nb_mb); - if (!par) - return AVERROR(ENOMEM); - - for (y = 0; y < p->alloc_mb_height; y++) - for (x = 0; x < p->alloc_mb_width; x++) { - const unsigned int block_idx = y * p->alloc_mb_width + x; - const unsigned int mb_xy = y * p->alloc_mb_stride + x; - AVVideoBlockParams *b = av_video_enc_params_block(par, block_idx); - - b->src_x = x * 16; - b->src_y = y * 16; - b->w = 16; - b->h = 16; - - b->delta_qp = p->qscale_table[mb_xy] * mult; - } - - return 0; -} - static inline int hpel_motion_lowres(MpegEncContext *s, uint8_t *dest, uint8_t *src, int field_based, int field_select, @@ -2274,13 +1746,6 @@ void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]) else mpv_reconstruct_mb_internal(s, block, 0, 0); } -void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) -{ - ff_draw_horiz_band(s->avctx, s->current_picture_ptr->f, - s->last_picture_ptr ? s->last_picture_ptr->f : NULL, y, h, s->picture_structure, - s->first_field, s->low_delay); -} - void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics const int uvlinesize = s->current_picture.f->linesize[1]; @@ -2314,35 +1779,6 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename } } -void ff_mpeg_flush(AVCodecContext *avctx){ - int i; - MpegEncContext *s = avctx->priv_data; - - if (!s->picture) - return; - - for (i = 0; i < MAX_PICTURE_COUNT; i++) - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; - - ff_mpeg_unref_picture(s->avctx, &s->current_picture); - ff_mpeg_unref_picture(s->avctx, &s->last_picture); - ff_mpeg_unref_picture(s->avctx, &s->next_picture); - - s->mb_x= s->mb_y= 0; - -#if FF_API_FLAG_TRUNCATED - s->parse_context.state= -1; - s->parse_context.frame_start_found= 0; - s->parse_context.overread= 0; - s->parse_context.overread_index= 0; - s->parse_context.index= 0; - s->parse_context.last_index= 0; -#endif - s->bitstream_buffer_size=0; - s->pp_time=0; -} - /** * set qscale and update qscale dependent variables. */ @@ -2359,9 +1795,3 @@ void ff_set_qscale(MpegEncContext * s, int qscale) s->y_dc_scale= s->y_dc_scale_table[ qscale ]; s->c_dc_scale= s->c_dc_scale_table[ s->chroma_qscale ]; } - -void ff_mpv_report_decode_progress(MpegEncContext *s) -{ - if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) - ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); -} diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index fabcce2436..1c14f5b0f0 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -679,10 +679,32 @@ void ff_mpv_common_init_neon(MpegEncContext *s); void ff_mpv_common_init_ppc(MpegEncContext *s); void ff_mpv_common_init_x86(MpegEncContext *s); void ff_mpv_common_init_mips(MpegEncContext *s); +/** + * Initialize an MpegEncContext's thread contexts. Presumes that + * slice_context_count is already set and that all the fields + * that are freed/reset in free_duplicate_context() are NULL. + */ +int ff_mpv_init_duplicate_contexts(MpegEncContext *s); +/** + * Initialize and allocates MpegEncContext fields dependent on the resolution. + */ +int ff_mpv_init_context_frame(MpegEncContext *s); +/** + * Frees and resets MpegEncContext fields depending on the resolution + * as well as the slice thread contexts. + * Is used during resolution changes to avoid a full reinitialization of the + * codec. + */ +void ff_mpv_free_context_frame(MpegEncContext *s); int ff_mpv_common_frame_size_change(MpegEncContext *s); void ff_mpv_common_end(MpegEncContext *s); +/** + * Initialize the given MpegEncContext for decoding. + * the changed fields will not depend upon + * the prior state of the MpegEncContext. + */ void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx); void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]); void ff_mpv_report_decode_progress(MpegEncContext *s); diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c new file mode 100644 index 0000000000..8b625d2835 --- /dev/null +++ b/libavcodec/mpegvideo_dec.c @@ -0,0 +1,583 @@ +/* + * Common mpeg video decoding code + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/video_enc_params.h" + +#include "avcodec.h" +#include "internal.h" +#include "mpegutils.h" +#include "mpegvideo.h" +#include "thread.h" + +void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) +{ + ff_mpv_common_defaults(s); + + s->avctx = avctx; + s->width = avctx->coded_width; + s->height = avctx->coded_height; + s->codec_id = avctx->codec->id; + s->workaround_bugs = avctx->workaround_bugs; + + /* convert fourcc to upper case */ + s->codec_tag = ff_toupper4(avctx->codec_tag); +} + +int ff_mpeg_update_thread_context(AVCodecContext *dst, + const AVCodecContext *src) +{ + MpegEncContext *const s1 = src->priv_data; + MpegEncContext *const s = dst->priv_data; + int ret; + + if (dst == src) + return 0; + + av_assert0(s != s1); + + // FIXME can parameters change on I-frames? + // in that case dst may need a reinit + if (!s->context_initialized) { + int err; + memcpy(s, s1, sizeof(*s)); + + s->avctx = dst; + s->bitstream_buffer = NULL; + s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; + + if (s1->context_initialized) { +// s->picture_range_start += MAX_PICTURE_COUNT; +// s->picture_range_end += MAX_PICTURE_COUNT; + ff_mpv_idct_init(s); + if ((err = ff_mpv_common_init(s)) < 0) { + memset(s, 0, sizeof(*s)); + s->avctx = dst; + return err; + } + } + } + + if (s->height != s1->height || s->width != s1->width || s->context_reinit) { + s->height = s1->height; + s->width = s1->width; + if ((ret = ff_mpv_common_frame_size_change(s)) < 0) + return ret; + } + + s->avctx->coded_height = s1->avctx->coded_height; + s->avctx->coded_width = s1->avctx->coded_width; + s->avctx->width = s1->avctx->width; + s->avctx->height = s1->avctx->height; + + s->quarter_sample = s1->quarter_sample; + + s->coded_picture_number = s1->coded_picture_number; + s->picture_number = s1->picture_number; + + av_assert0(!s->picture || s->picture != s1->picture); + if (s->picture) + for (int i = 0; i < MAX_PICTURE_COUNT; i++) { + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + if (s1->picture && s1->picture[i].f->buf[0] && + (ret = ff_mpeg_ref_picture(s->avctx, &s->picture[i], &s1->picture[i])) < 0) + return ret; + } + +#define UPDATE_PICTURE(pic)\ +do {\ + ff_mpeg_unref_picture(s->avctx, &s->pic);\ + if (s1->pic.f && s1->pic.f->buf[0])\ + ret = ff_mpeg_ref_picture(s->avctx, &s->pic, &s1->pic);\ + else\ + ret = ff_update_picture_tables(&s->pic, &s1->pic);\ + if (ret < 0)\ + return ret;\ +} while (0) + + UPDATE_PICTURE(current_picture); + UPDATE_PICTURE(last_picture); + UPDATE_PICTURE(next_picture); + +#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ + ((pic && pic >= old_ctx->picture && \ + pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ + &new_ctx->picture[pic - old_ctx->picture] : NULL) + + s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); + s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); + s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); + + // Error/bug resilience + s->next_p_frame_damaged = s1->next_p_frame_damaged; + s->workaround_bugs = s1->workaround_bugs; + s->padding_bug_score = s1->padding_bug_score; + + // MPEG-4 timing info + memcpy(&s->last_time_base, &s1->last_time_base, + (char *) &s1->pb_field_time + sizeof(s1->pb_field_time) - + (char *) &s1->last_time_base); + + // B-frame info + s->max_b_frames = s1->max_b_frames; + s->low_delay = s1->low_delay; + s->droppable = s1->droppable; + + // DivX handling (doesn't work) + s->divx_packed = s1->divx_packed; + + if (s1->bitstream_buffer) { + if (s1->bitstream_buffer_size + + AV_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) { + av_fast_malloc(&s->bitstream_buffer, + &s->allocated_bitstream_buffer_size, + s1->allocated_bitstream_buffer_size); + if (!s->bitstream_buffer) { + s->bitstream_buffer_size = 0; + return AVERROR(ENOMEM); + } + } + s->bitstream_buffer_size = s1->bitstream_buffer_size; + memcpy(s->bitstream_buffer, s1->bitstream_buffer, + s1->bitstream_buffer_size); + memset(s->bitstream_buffer + s->bitstream_buffer_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + } + + // linesize-dependent scratch buffer allocation + if (!s->sc.edge_emu_buffer) + if (s1->linesize) { + if (ff_mpeg_framesize_alloc(s->avctx, &s->me, + &s->sc, s1->linesize) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " + "scratch buffers.\n"); + return AVERROR(ENOMEM); + } + } else { + av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " + "be allocated due to unknown size.\n"); + } + + // MPEG-2/interlacing info + memcpy(&s->progressive_sequence, &s1->progressive_sequence, + (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); + + return 0; +} + +int ff_mpv_common_frame_size_change(MpegEncContext *s) +{ + int err = 0; + + if (!s->context_initialized) + return AVERROR(EINVAL); + + ff_mpv_free_context_frame(s); + + if (s->picture) + for (int i = 0; i < MAX_PICTURE_COUNT; i++) + s->picture[i].needs_realloc = 1; + + s->last_picture_ptr = + s->next_picture_ptr = + s->current_picture_ptr = NULL; + + // init + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) + s->mb_height = (s->height + 31) / 32 * 2; + else + s->mb_height = (s->height + 15) / 16; + + if ((s->width || s->height) && + (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0) + goto fail; + + /* set chroma shifts */ + err = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &s->chroma_x_shift, + &s->chroma_y_shift); + if (err < 0) + goto fail; + + if ((err = ff_mpv_init_context_frame(s))) + goto fail; + + memset(s->thread_context, 0, sizeof(s->thread_context)); + s->thread_context[0] = s; + + if (s->width && s->height) { + err = ff_mpv_init_duplicate_contexts(s); + if (err < 0) + goto fail; + } + s->context_reinit = 0; + + return 0; + fail: + ff_mpv_free_context_frame(s); + s->context_reinit = 1; + return err; +} + +static int alloc_picture(MpegEncContext *s, Picture *pic) +{ + return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, 0, 0, + s->chroma_x_shift, s->chroma_y_shift, s->out_format, + s->mb_stride, s->mb_width, s->mb_height, s->b8_stride, + &s->linesize, &s->uvlinesize); +} + +static void gray_frame(AVFrame *frame) +{ + int h_chroma_shift, v_chroma_shift; + + av_pix_fmt_get_chroma_sub_sample(frame->format, &h_chroma_shift, &v_chroma_shift); + + for (int i = 0; i < frame->height; i++) + memset(frame->data[0] + frame->linesize[0] * i, 0x80, frame->width); + for (int i = 0; i < AV_CEIL_RSHIFT(frame->height, v_chroma_shift); i++) { + memset(frame->data[1] + frame->linesize[1] * i, + 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); + memset(frame->data[2] + frame->linesize[2] * i, + 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); + } +} + +/** + * generic function called after decoding + * the header and before a frame is decoded. + */ +int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) +{ + Picture *pic; + int idx, ret; + + s->mb_skipped = 0; + + if (!ff_thread_can_start_frame(avctx)) { + av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + + /* mark & release old frames */ + if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && + s->last_picture_ptr != s->next_picture_ptr && + s->last_picture_ptr->f->buf[0]) { + ff_mpeg_unref_picture(s->avctx, s->last_picture_ptr); + } + + /* release forgotten pictures */ + /* if (MPEG-124 / H.263) */ + for (int i = 0; i < MAX_PICTURE_COUNT; i++) { + if (&s->picture[i] != s->last_picture_ptr && + &s->picture[i] != s->next_picture_ptr && + s->picture[i].reference && !s->picture[i].needs_realloc) { + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + } + } + + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); + + /* release non reference frames */ + for (int i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference) + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + } + + if (s->current_picture_ptr && !s->current_picture_ptr->f->buf[0]) { + // we already have an unused image + // (maybe it was set before reading the header) + pic = s->current_picture_ptr; + } else { + idx = ff_find_unused_picture(s->avctx, s->picture, 0); + if (idx < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return idx; + } + pic = &s->picture[idx]; + } + + pic->reference = 0; + if (!s->droppable) { + if (s->pict_type != AV_PICTURE_TYPE_B) + pic->reference = 3; + } + + pic->f->coded_picture_number = s->coded_picture_number++; + + if (alloc_picture(s, pic) < 0) + return -1; + + s->current_picture_ptr = pic; + // FIXME use only the vars from current_pic + s->current_picture_ptr->f->top_field_first = s->top_field_first; + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || + s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (s->picture_structure != PICT_FRAME) + s->current_picture_ptr->f->top_field_first = + (s->picture_structure == PICT_TOP_FIELD) == s->first_field; + } + s->current_picture_ptr->f->interlaced_frame = !s->progressive_frame && + !s->progressive_sequence; + s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; + + s->current_picture_ptr->f->pict_type = s->pict_type; + // if (s->avctx->flags && AV_CODEC_FLAG_QSCALE) + // s->current_picture_ptr->quality = s->new_picture_ptr->quality; + s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, + s->current_picture_ptr)) < 0) + return ret; + + if (s->pict_type != AV_PICTURE_TYPE_B) { + s->last_picture_ptr = s->next_picture_ptr; + if (!s->droppable) + s->next_picture_ptr = s->current_picture_ptr; + } + ff_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", + s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, + s->last_picture_ptr ? s->last_picture_ptr->f->data[0] : NULL, + s->next_picture_ptr ? s->next_picture_ptr->f->data[0] : NULL, + s->current_picture_ptr ? s->current_picture_ptr->f->data[0] : NULL, + s->pict_type, s->droppable); + + if ((!s->last_picture_ptr || !s->last_picture_ptr->f->buf[0]) && + (s->pict_type != AV_PICTURE_TYPE_I)) { + int h_chroma_shift, v_chroma_shift; + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &h_chroma_shift, &v_chroma_shift); + if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0]) + av_log(avctx, AV_LOG_DEBUG, + "allocating dummy last picture for B frame\n"); + else if (s->pict_type != AV_PICTURE_TYPE_I) + av_log(avctx, AV_LOG_ERROR, + "warning: first frame is no keyframe\n"); + + /* Allocate a dummy frame */ + idx = ff_find_unused_picture(s->avctx, s->picture, 0); + if (idx < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return idx; + } + s->last_picture_ptr = &s->picture[idx]; + + s->last_picture_ptr->reference = 3; + s->last_picture_ptr->f->key_frame = 0; + s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; + + if (alloc_picture(s, s->last_picture_ptr) < 0) { + s->last_picture_ptr = NULL; + return -1; + } + + if (!avctx->hwaccel) { + for (int i = 0; i < avctx->height; i++) + memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, + 0x80, avctx->width); + if (s->last_picture_ptr->f->data[2]) { + for (int i = 0; i < AV_CEIL_RSHIFT(avctx->height, v_chroma_shift); i++) { + memset(s->last_picture_ptr->f->data[1] + s->last_picture_ptr->f->linesize[1]*i, + 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); + memset(s->last_picture_ptr->f->data[2] + s->last_picture_ptr->f->linesize[2]*i, + 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); + } + } + + if (s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263) { + for (int i = 0; i < avctx->height; i++) + memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0] * i, + 16, avctx->width); + } + } + + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); + } + if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) && + s->pict_type == AV_PICTURE_TYPE_B) { + /* Allocate a dummy frame */ + idx = ff_find_unused_picture(s->avctx, s->picture, 0); + if (idx < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return idx; + } + s->next_picture_ptr = &s->picture[idx]; + + s->next_picture_ptr->reference = 3; + s->next_picture_ptr->f->key_frame = 0; + s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; + + if (alloc_picture(s, s->next_picture_ptr) < 0) { + s->next_picture_ptr = NULL; + return -1; + } + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 1); + } + +#if 0 // BUFREF-FIXME + memset(s->last_picture.f->data, 0, sizeof(s->last_picture.f->data)); + memset(s->next_picture.f->data, 0, sizeof(s->next_picture.f->data)); +#endif + if (s->last_picture_ptr) { + if (s->last_picture_ptr->f->buf[0] && + (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture, + s->last_picture_ptr)) < 0) + return ret; + } + if (s->next_picture_ptr) { + if (s->next_picture_ptr->f->buf[0] && + (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture, + s->next_picture_ptr)) < 0) + return ret; + } + + av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && + s->last_picture_ptr->f->buf[0])); + + if (s->picture_structure != PICT_FRAME) { + for (int i = 0; i < 4; i++) { + if (s->picture_structure == PICT_BOTTOM_FIELD) { + s->current_picture.f->data[i] += + s->current_picture.f->linesize[i]; + } + s->current_picture.f->linesize[i] *= 2; + s->last_picture.f->linesize[i] *= 2; + s->next_picture.f->linesize[i] *= 2; + } + } + + /* set dequantizer, we can't do it during init as + * it might change for MPEG-4 and we can't do it in the header + * decode as init is not called for MPEG-4 there yet */ + if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; + s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; + } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { + s->dct_unquantize_intra = s->dct_unquantize_h263_intra; + s->dct_unquantize_inter = s->dct_unquantize_h263_inter; + } else { + s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra; + s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; + } + + if (s->avctx->debug & FF_DEBUG_NOMC) + gray_frame(s->current_picture_ptr->f); + + return 0; +} + +/* called after a frame has been decoded. */ +void ff_mpv_frame_end(MpegEncContext *s) +{ + emms_c(); + + if (s->current_picture.reference) + ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); +} + +void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) +{ + ff_print_debug_info2(s->avctx, pict, s->mbskip_table, p->mb_type, + p->qscale_table, p->motion_val, + s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample); +} + +int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type) +{ + AVVideoEncParams *par; + int mult = (qp_type == FF_QSCALE_TYPE_MPEG1) ? 2 : 1; + unsigned int nb_mb = p->alloc_mb_height * p->alloc_mb_width; + + if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS)) + return 0; + + par = av_video_enc_params_create_side_data(f, AV_VIDEO_ENC_PARAMS_MPEG2, nb_mb); + if (!par) + return AVERROR(ENOMEM); + + for (unsigned y = 0; y < p->alloc_mb_height; y++) + for (unsigned x = 0; x < p->alloc_mb_width; x++) { + const unsigned int block_idx = y * p->alloc_mb_width + x; + const unsigned int mb_xy = y * p->alloc_mb_stride + x; + AVVideoBlockParams *const b = av_video_enc_params_block(par, block_idx); + + b->src_x = x * 16; + b->src_y = y * 16; + b->w = 16; + b->h = 16; + + b->delta_qp = p->qscale_table[mb_xy] * mult; + } + + return 0; +} + +void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) +{ + ff_draw_horiz_band(s->avctx, s->current_picture_ptr->f, + s->last_picture_ptr ? s->last_picture_ptr->f : NULL, + y, h, s->picture_structure, + s->first_field, s->low_delay); +} + +void ff_mpeg_flush(AVCodecContext *avctx) +{ + MpegEncContext *const s = avctx->priv_data; + + if (!s->picture) + return; + + for (int i = 0; i < MAX_PICTURE_COUNT; i++) + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; + + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); + + s->mb_x = s->mb_y = 0; + +#if FF_API_FLAG_TRUNCATED + s->parse_context.state = -1; + s->parse_context.frame_start_found = 0; + s->parse_context.overread = 0; + s->parse_context.overread_index = 0; + s->parse_context.index = 0; + s->parse_context.last_index = 0; +#endif + s->bitstream_buffer_size = 0; + s->pp_time = 0; +} + +void ff_mpv_report_decode_progress(MpegEncContext *s) +{ + if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) + ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); +} From ab54956edda3b6f721a4c7c8b0862d29a4d190a4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 24 Dec 2021 02:13:41 +0100 Subject: [PATCH 754/894] configure: Add new mpegvideodec CONFIG_EXTRA This allows to remove the spurious dependencies of mpegvideo encoders on error_resilience; some other components that do not use mpegvideo to its fullest turned out to not need it either. Adding a new CONFIG_EXTRA needs a reconfigure to take effect. In order to force this a few unnecessary headers from lavfi/allfilters.c have been removed. Signed-off-by: Andreas Rheinhardt --- configure | 26 ++++++++++++++------------ libavcodec/Makefile | 5 +++-- libavcodec/h264dec.c | 2 +- libavcodec/mpegvideo.c | 2 +- libavfilter/allfilters.c | 2 -- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/configure b/configure index 729e9b5ac7..b23e0333de 100755 --- a/configure +++ b/configure @@ -2478,6 +2478,7 @@ CONFIG_EXTRA=" mpegaudioheader mpeg4audio mpegvideo + mpegvideodec mpegvideoenc mss34dsp pixblockdsp @@ -2727,7 +2728,8 @@ me_cmp_select="fdctdsp idctdsp pixblockdsp" mpeg_er_select="error_resilience" mpegaudio_select="mpegaudiodsp mpegaudioheader" mpegaudiodsp_select="dct" -mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp mpeg_er videodsp" +mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp videodsp" +mpegvideodec_select="mpegvideo mpeg_er" mpegvideoenc_select="aandcttables me_cmp mpegvideo pixblockdsp qpeldsp" vc1dsp_select="h264chroma qpeldsp startcode" rdft_select="fft" @@ -2816,9 +2818,9 @@ fraps_decoder_select="bswapdsp huffman" g2m_decoder_deps="zlib" g2m_decoder_select="blockdsp idctdsp jpegtables" g729_decoder_select="audiodsp" -h261_decoder_select="mpegvideo" +h261_decoder_select="mpegvideodec" h261_encoder_select="mpegvideoenc" -h263_decoder_select="h263_parser h263dsp mpegvideo qpeldsp" +h263_decoder_select="h263_parser h263dsp mpegvideodec qpeldsp" h263_encoder_select="h263dsp mpegvideoenc" h263i_decoder_select="h263_decoder" h263p_decoder_select="h263_decoder" @@ -2840,7 +2842,7 @@ indeo3_decoder_select="hpeldsp" indeo4_decoder_select="ividsp" indeo5_decoder_select="ividsp" interplay_video_decoder_select="hpeldsp" -ipu_decoder_select="mpegvideo" +ipu_decoder_select="mpegvideodec" jpegls_decoder_select="mjpeg_decoder" jv_decoder_select="blockdsp" lagarith_decoder_select="llviddsp" @@ -2870,10 +2872,10 @@ mp3on4_decoder_select="mpegaudio mpeg4audio" mp3on4float_decoder_select="mpegaudio mpeg4audio" mpc7_decoder_select="bswapdsp mpegaudiodsp" mpc8_decoder_select="mpegaudiodsp" -mpegvideo_decoder_select="mpegvideo" -mpeg1video_decoder_select="mpegvideo" +mpegvideo_decoder_select="mpegvideodec" +mpeg1video_decoder_select="mpegvideodec" mpeg1video_encoder_select="mpegvideoenc h263dsp" -mpeg2video_decoder_select="mpegvideo" +mpeg2video_decoder_select="mpegvideodec" mpeg2video_encoder_select="mpegvideoenc h263dsp" mpeg4_decoder_select="h263_decoder mpeg4video_parser" mpeg4_encoder_select="h263_encoder" @@ -2884,7 +2886,7 @@ msmpeg4v2_decoder_select="h263_decoder" msmpeg4v2_encoder_select="h263_encoder" msmpeg4v3_decoder_select="h263_decoder" msmpeg4v3_encoder_select="h263_encoder" -mss2_decoder_select="mpegvideo qpeldsp vc1_decoder" +mss2_decoder_select="mpegvideodec qpeldsp vc1_decoder" mts2_decoder_select="jpegtables mss34dsp" mv30_decoder_select="aandcttables blockdsp" mvha_decoder_deps="zlib" @@ -2917,8 +2919,8 @@ rv10_decoder_select="h263_decoder" rv10_encoder_select="h263_encoder" rv20_decoder_select="h263_decoder" rv20_encoder_select="h263_encoder" -rv30_decoder_select="golomb h264pred h264qpel mpegvideo rv34dsp" -rv40_decoder_select="golomb h264pred h264qpel mpegvideo rv34dsp" +rv30_decoder_select="golomb h264pred h264qpel mpegvideodec rv34dsp" +rv40_decoder_select="golomb h264pred h264qpel mpegvideodec rv34dsp" screenpresso_decoder_deps="zlib" shorten_decoder_select="bswapdsp" sipr_decoder_select="lsp" @@ -2954,7 +2956,7 @@ txd_decoder_select="texturedsp" utvideo_decoder_select="bswapdsp llviddsp" utvideo_encoder_select="bswapdsp huffman llvidencdsp" vble_decoder_select="llviddsp" -vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideo vc1dsp" +vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideodec vc1dsp" vc1image_decoder_select="vc1_decoder" vorbis_decoder_select="mdct" vorbis_encoder_select="audio_frame_queue mdct" @@ -3250,7 +3252,7 @@ h264_parser_select="atsc_a53 golomb h264dsp h264parse" hevc_parser_select="hevcparse" mpegaudio_parser_select="mpegaudioheader" mpegvideo_parser_select="mpegvideo" -mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" +mpeg4video_parser_select="h263dsp mpegvideodec qpeldsp" vc1_parser_select="vc1dsp" # bitstream_filters diff --git a/libavcodec/Makefile b/libavcodec/Makefile index fc07308615..7dc4ccb85f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -125,10 +125,11 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_float.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o -OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideo_dec.o mpegvideodsp.o rl.o \ - mpegvideo_motion.o mpegutils.o \ +OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ + mpegvideo_motion.o \ mpegvideodata.o mpegpicture.o \ to_upper4.o +OBJS-$(CONFIG_MPEGVIDEODEC) += mpegvideo_dec.o mpegutils.o OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ motion_est.o ratecontrol.o \ mpegvideoencdsp.o diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 6a5bf51f5d..7f10026340 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -939,7 +939,7 @@ static int finalize_frame(H264Context *h, AVFrame *dst, H264Picture *out, int *g *got_frame = 1; - if (CONFIG_MPEGVIDEO) { + if (CONFIG_MPEGVIDEODEC) { ff_print_debug_info2(h->avctx, dst, NULL, out->mb_type, out->qscale_table, diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index a2c4e14b6e..1c2b28f450 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -658,7 +658,7 @@ int ff_mpv_init_context_frame(MpegEncContext *s) return AVERROR(ENOMEM); memset(s->mbintra_table, 1, mb_array_size); - return s->encoding ? 0 : ff_mpeg_er_init(s); + return !CONFIG_MPEGVIDEODEC || s->encoding ? 0 : ff_mpeg_er_init(s); } static void clear_context(MpegEncContext *s) diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index caa755320e..dac615d7df 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -19,9 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/thread.h" #include "avfilter.h" -#include "config.h" extern const AVFilter ff_af_abench; extern const AVFilter ff_af_acompressor; From 519c2c1a86bdd6a81ddc1a493bb53fb6fe3a645c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Dec 2021 04:57:02 +0100 Subject: [PATCH 755/894] configure: Remove mpegvideo dependency on me_cmp Forgotten in cf1e0786ed64e69614760bfb4ecd7adbde8e6094. (Both mpegvideodec as well as mpegvideoenc use me_cmp, so this doesn't affect them.) Signed-off-by: Andreas Rheinhardt --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index b23e0333de..64538b17e2 100755 --- a/configure +++ b/configure @@ -2728,7 +2728,7 @@ me_cmp_select="fdctdsp idctdsp pixblockdsp" mpeg_er_select="error_resilience" mpegaudio_select="mpegaudiodsp mpegaudioheader" mpegaudiodsp_select="dct" -mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp videodsp" +mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp videodsp" mpegvideodec_select="mpegvideo mpeg_er" mpegvideoenc_select="aandcttables me_cmp mpegvideo pixblockdsp qpeldsp" vc1dsp_select="h264chroma qpeldsp startcode" From bf2c34a01af4fd5d18e7e978e148ec3ad5fc43c5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 24 Dec 2021 02:32:28 +0100 Subject: [PATCH 756/894] avcodec/mpegvideo_enc: Improve inlining of chroma_format encode_mb() calls encode_mb_internal() three times, once for each supported chroma format. The reason for this is that some chroma format dependent parameters can then be inlined as encode_mb_internal() is marked as av_always_inline. Yet the most basic parameters based upon chroma format have not been inlined: The chroma format itself and the chroma subsampling parameters. This commit does so. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 0279816d3c..0ac8886246 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -2030,7 +2030,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, int motion_x, int motion_y, int mb_block_height, int mb_block_width, - int mb_block_count) + int mb_block_count, + int chroma_x_shift, + int chroma_y_shift, + int chroma_format) { int16_t weight[12][64]; int16_t orig[12][64]; @@ -2087,8 +2090,8 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, if((mb_x * 16 + 16 > s->width || mb_y * 16 + 16 > s->height) && s->codec_id != AV_CODEC_ID_AMV){ uint8_t *ebuf = s->sc.edge_emu_buffer + 38 * wrap_y; - int cw = (s->width + s->chroma_x_shift) >> s->chroma_x_shift; - int ch = (s->height + s->chroma_y_shift) >> s->chroma_y_shift; + int cw = (s->width + chroma_x_shift) >> chroma_x_shift; + int ch = (s->height + chroma_y_shift) >> chroma_y_shift; s->vdsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, wrap_y, 16, 16, mb_x * 16, mb_y * 16, @@ -2128,8 +2131,8 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, dct_offset = wrap_y; uv_dct_offset = wrap_c; wrap_y <<= 1; - if (s->chroma_format == CHROMA_422 || - s->chroma_format == CHROMA_444) + if (chroma_format == CHROMA_422 || + chroma_format == CHROMA_444) wrap_c <<= 1; } } @@ -2146,10 +2149,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } else { s->pdsp.get_pixels(s->block[4], ptr_cb, wrap_c); s->pdsp.get_pixels(s->block[5], ptr_cr, wrap_c); - if (!s->chroma_y_shift && s->chroma_x_shift) { /* 422 */ + if (chroma_format == CHROMA_422) { s->pdsp.get_pixels(s->block[6], ptr_cb + uv_dct_offset, wrap_c); s->pdsp.get_pixels(s->block[7], ptr_cr + uv_dct_offset, wrap_c); - } else if (!s->chroma_y_shift && !s->chroma_x_shift) { /* 444 */ + } else if (chroma_format == CHROMA_444) { s->pdsp.get_pixels(s->block[ 6], ptr_cb + 8, wrap_c); s->pdsp.get_pixels(s->block[ 7], ptr_cr + 8, wrap_c); s->pdsp.get_pixels(s->block[ 8], ptr_cb + uv_dct_offset, wrap_c); @@ -2213,7 +2216,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, dct_offset = wrap_y; uv_dct_offset = wrap_c; wrap_y <<= 1; - if (s->chroma_format == CHROMA_422) + if (chroma_format == CHROMA_422) wrap_c <<= 1; } } @@ -2232,7 +2235,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } else { s->pdsp.diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); s->pdsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); - if (!s->chroma_y_shift) { /* 422 */ + if (!chroma_y_shift) { /* 422 */ s->pdsp.diff_pixels(s->block[6], ptr_cb + uv_dct_offset, dest_cb + uv_dct_offset, wrap_c); s->pdsp.diff_pixels(s->block[7], ptr_cr + uv_dct_offset, @@ -2257,7 +2260,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, skip_dct[4] = 1; if (s->mecc.sad[1](NULL, ptr_cr, dest_cr, wrap_c, 8) < 20 * s->qscale) skip_dct[5] = 1; - if (!s->chroma_y_shift) { /* 422 */ + if (!chroma_y_shift) { /* 422 */ if (s->mecc.sad[1](NULL, ptr_cb + uv_dct_offset, dest_cb + uv_dct_offset, wrap_c, 8) < 20 * s->qscale) @@ -2283,7 +2286,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, get_visual_weight(weight[4], ptr_cb , wrap_c); if (!skip_dct[5]) get_visual_weight(weight[5], ptr_cr , wrap_c); - if (!s->chroma_y_shift) { /* 422 */ + if (!chroma_y_shift) { /* 422 */ if (!skip_dct[6]) get_visual_weight(weight[6], ptr_cb + uv_dct_offset, wrap_c); @@ -2341,7 +2344,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, s->block_last_index[5] = 0; s->block[4][0] = s->block[5][0] = (1024 + s->c_dc_scale / 2) / s->c_dc_scale; - if (!s->chroma_y_shift) { /* 422 / 444 */ + if (!chroma_y_shift) { /* 422 / 444 */ for (i=6; i<12; i++) { s->block_last_index[i] = 0; s->block[i][0] = s->block[4][0]; @@ -2413,9 +2416,12 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, static av_always_inline void encode_mb(MpegEncContext *s, int motion_x, int motion_y) { - if (s->chroma_format == CHROMA_420) encode_mb_internal(s, motion_x, motion_y, 8, 8, 6); - else if (s->chroma_format == CHROMA_422) encode_mb_internal(s, motion_x, motion_y, 16, 8, 8); - else encode_mb_internal(s, motion_x, motion_y, 16, 16, 12); + if (s->chroma_format == CHROMA_420) + encode_mb_internal(s, motion_x, motion_y, 8, 8, 6, 1, 1, CHROMA_420); + else if (s->chroma_format == CHROMA_422) + encode_mb_internal(s, motion_x, motion_y, 16, 8, 8, 1, 0, CHROMA_422); + else + encode_mb_internal(s, motion_x, motion_y, 16, 16, 12, 0, 0, CHROMA_444); } static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext *s, int type){ From 58f6d1e758b0617cbd30a3ccef647ec655a50ea9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 24 Dec 2021 03:00:29 +0100 Subject: [PATCH 757/894] avcodec/mpegvideo_enc: Remove dead code at compile time There are no encoders for interlaced dct that support 4:4:4. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 0ac8886246..15b6669e46 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -2035,6 +2035,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, int chroma_y_shift, int chroma_format) { +/* Interlaced DCT is only possible with MPEG-2 and MPEG-4 + * and neither of these encoders currently supports 444. */ +#define INTERLACED_DCT(s) ((chroma_format == CHROMA_420 || chroma_format == CHROMA_422) && \ + (s)->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) int16_t weight[12][64]; int16_t orig[12][64]; const int mb_x = s->mb_x; @@ -2112,7 +2116,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } if (s->mb_intra) { - if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + if (INTERLACED_DCT(s)) { int progressive_score, interlaced_score; s->interlaced_dct = 0; @@ -2191,7 +2195,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, op_pix, op_qpix); } - if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + if (INTERLACED_DCT(s)) { int progressive_score, interlaced_score; s->interlaced_dct = 0; From d91b5020ec4b9b8d356e0dd7b1bee2438c948b0e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Dec 2021 02:07:53 +0100 Subject: [PATCH 758/894] avcodec/mpeg12enc: Also inline chroma subsampling ff_mpeg1_encode_mb() contains two inlined calls to mpeg1_encode_mb_internal(); these calls are supposed to inline the properties depending upon the color space used. Yet inlining vertical chroma subsampling (which allows to remove complete branches and blocks depending upon them) has been forgotten. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12enc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 3692494713..1437ac421c 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -773,7 +773,8 @@ next_coef: static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y, - int mb_block_count) + int mb_block_count, + int chroma_y_shift) { int i, cbp; const int mb_x = s->mb_x; @@ -918,7 +919,7 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, s->mv_bits += get_bits_diff(s); } if (cbp) { - if (s->chroma_y_shift) { + if (chroma_y_shift) { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); @@ -1025,7 +1026,7 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, } s->mv_bits += get_bits_diff(s); if (cbp) { - if (s->chroma_y_shift) { + if (chroma_y_shift) { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); @@ -1052,9 +1053,9 @@ void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y) { if (s->chroma_format == CHROMA_420) - mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6); + mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6, 1); else - mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8); + mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8, 0); } static av_cold void mpeg12_encode_init_static(void) From c037f3fc7ded735c054c6c3d003c16af0e94cf42 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Dec 2021 02:38:59 +0100 Subject: [PATCH 759/894] avcodec/mpeg12enc: Partially inline whether codec is MPEG-1 MPEG-1 only supports 4:2:0, so one can optimize away the checks for whether one encodes MPEG-1 in codepaths that encode 4:2:2. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12enc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 1437ac421c..97d497d619 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -776,6 +776,8 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, int mb_block_count, int chroma_y_shift) { +/* MPEG-1 is always 420. */ +#define IS_MPEG1(s) (chroma_y_shift == 1 && (s)->codec_id == AV_CODEC_ID_MPEG1VIDEO) int i, cbp; const int mb_x = s->mb_x; const int mb_y = s->mb_y; @@ -789,7 +791,7 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, if (cbp == 0 && !first_mb && s->mv_type == MV_TYPE_16X16 && (mb_x != s->mb_width - 1 || - (mb_y != s->end_mb_y - 1 && s->codec_id == AV_CODEC_ID_MPEG1VIDEO)) && + (mb_y != s->end_mb_y - 1 && IS_MPEG1(s))) && ((s->pict_type == AV_PICTURE_TYPE_P && (motion_x | motion_y) == 0) || (s->pict_type == AV_PICTURE_TYPE_B && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) From 8abc192236a5afe764e4fc76dcae9874fb3bedaa Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 25 Dec 2021 03:25:02 +0100 Subject: [PATCH 760/894] avcodec/mpeg12enc: Inline constants Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12enc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 97d497d619..e28aa809d2 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -621,10 +621,8 @@ static inline void put_mb_modes(MpegEncContext *s, int n, int bits, static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code) { if (val == 0) { - /* zero vector */ - put_bits(&s->pb, - ff_mpeg12_mbMotionVectorTable[0][1], - ff_mpeg12_mbMotionVectorTable[0][0]); + /* zero vector, corresponds to ff_mpeg12_mbMotionVectorTable[0] */ + put_bits(&s->pb, 1, 0x01); } else { int code, sign, bits; int bit_size = f_or_b_code - 1; @@ -746,8 +744,10 @@ next_coef: put_bits(&s->pb, table_vlc[code][1] + 1, (table_vlc[code][0] << 1) + sign); } else { - /* escape seems to be pretty rare <5% so I do not optimize it */ - put_bits(&s->pb, table_vlc[111][1], table_vlc[111][0]); + /* Escape seems to be pretty rare <5% so I do not optimize it; + * the following value is the common escape value for both + * possible tables (i.e. table_vlc[111]). */ + put_bits(&s->pb, 6, 0x01); /* escape: only clip in this case */ put_bits(&s->pb, 6, run); if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO) { @@ -1097,7 +1097,7 @@ static av_cold void mpeg12_encode_init_static(void) int len; if (mv == 0) { - len = ff_mpeg12_mbMotionVectorTable[0][1]; + len = 1; /* ff_mpeg12_mbMotionVectorTable[0][1] */ } else { int val, bit_size, code; @@ -1112,7 +1112,7 @@ static av_cold void mpeg12_encode_init_static(void) len = ff_mpeg12_mbMotionVectorTable[code][1] + 1 + bit_size; else - len = ff_mpeg12_mbMotionVectorTable[16][1] + + len = 10 /* ff_mpeg12_mbMotionVectorTable[16][1] */ + 2 + bit_size; } From 46f43f222e891a3da704ec711e859d13c2e9b5c6 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 4 Jan 2022 17:03:45 +0800 Subject: [PATCH 761/894] avcodec/videotoolbox: Fix undefined symbol with minimal configuration Please reproduced with the following minimal configure command: ./configure --enable-shared --disable-all --enable-avcodec --enable-decoder=h264 --enable-hwaccel=h264_videotoolbox You'll get below error: Undefined symbols for architecture x86_64: "_ff_videotoolbox_vpcc_extradata_create", referenced from: _videotoolbox_start in videotoolbox.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) Reported-by: Cameron Gutman Tested-by: Cameron Gutman Signed-off-by: Limin Wang --- libavcodec/videotoolbox.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 69beb3881f..51d4eacfd8 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -825,11 +825,13 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec if (data) CFDictionarySetValue(avc_info, CFSTR("hvcC"), data); break; +#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL case kCMVideoCodecType_VP9 : data = ff_videotoolbox_vpcc_extradata_create(avctx); if (data) CFDictionarySetValue(avc_info, CFSTR("vpcC"), data); break; +#endif default: break; } From 41f213c3bf629d549400e935e7f123e6cfa959ab Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 22 Dec 2021 23:07:38 +0800 Subject: [PATCH 762/894] avformat: reuse the common code for v210/v210x As suggested by Andreas Rheinhardt, most code of v210 demuxer is common code which is duplicated from rawvideodec, so it's better to move v210/v210x demuxer code to rawvideodec.c and reuse the common code. Signed-off-by: Limin Wang --- libavformat/Makefile | 4 +-- libavformat/rawvideodec.c | 54 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 8aba9d164c..c479ea998e 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -560,8 +560,8 @@ OBJS-$(CONFIG_TTY_DEMUXER) += tty.o sauce.o OBJS-$(CONFIG_TY_DEMUXER) += ty.o OBJS-$(CONFIG_TXD_DEMUXER) += txd.o OBJS-$(CONFIG_UNCODEDFRAMECRC_MUXER) += uncodedframecrcenc.o framehash.o -OBJS-$(CONFIG_V210_DEMUXER) += v210.o -OBJS-$(CONFIG_V210X_DEMUXER) += v210.o +OBJS-$(CONFIG_V210_DEMUXER) += rawvideodec.o +OBJS-$(CONFIG_V210X_DEMUXER) += rawvideodec.o OBJS-$(CONFIG_VAG_DEMUXER) += vag.o OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o vc1dec.o OBJS-$(CONFIG_VC1_MUXER) += rawenc.o diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 710724c2d1..68547fc50f 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -33,6 +33,8 @@ typedef struct RawVideoDemuxerContext { AVRational framerate; /**< AVRational describing framerate, set by a private option. */ } RawVideoDemuxerContext; +// v210 frame width is padded to multiples of 48 +#define GET_PACKET_SIZE(w, h) (((w + 47) / 48) * 48 * h * 8 / 3) static int rawvideo_read_header(AVFormatContext *ctx) { @@ -49,10 +51,13 @@ static int rawvideo_read_header(AVFormatContext *ctx) st->codecpar->codec_id = ctx->iformat->raw_codec_id; - if ((pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) { - av_log(ctx, AV_LOG_ERROR, "No such pixel format: %s.\n", - s->pixel_format); - return AVERROR(EINVAL); + if ((ctx->iformat->raw_codec_id != AV_CODEC_ID_V210) && + (ctx->iformat->raw_codec_id != AV_CODEC_ID_V210X)) { + if ((pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "No such pixel format: %s.\n", + s->pixel_format); + return AVERROR(EINVAL); + } } avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); @@ -84,6 +89,12 @@ static int rawvideo_read_header(AVFormatContext *ctx) } st->codecpar->codec_tag = tag; packet_size = s->width * s->height * pgroup / xinc; + } else if ((ctx->iformat->raw_codec_id == AV_CODEC_ID_V210) || + (ctx->iformat->raw_codec_id == AV_CODEC_ID_V210X)) { + pix_fmt = ctx->iformat->raw_codec_id == AV_CODEC_ID_V210 ? + AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV422P16; + + packet_size = GET_PACKET_SIZE(s->width, s->height); } else { packet_size = av_image_get_buffer_size(pix_fmt, s->width, s->height, 1); if (packet_size < 0) @@ -160,3 +171,38 @@ const AVInputFormat ff_bitpacked_demuxer = { .priv_class = &bitpacked_demuxer_class, }; #endif // CONFIG_BITPACKED_DEMUXER + +static const AVClass v210_demuxer_class = { + .class_name = "v210(x) demuxer", + .item_name = av_default_item_name, + .option = rawvideo_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +#if CONFIG_V210_DEMUXER +const AVInputFormat ff_v210_demuxer = { + .name = "v210", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .priv_data_size = sizeof(RawVideoDemuxerContext), + .read_header = rawvideo_read_header, + .read_packet = rawvideo_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "v210", + .raw_codec_id = AV_CODEC_ID_V210, + .priv_class = &v210_demuxer_class, +}; +#endif // CONFIG_V210_DEMUXER + +#if CONFIG_V210X_DEMUXER +const AVInputFormat ff_v210x_demuxer = { + .name = "v210x", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .priv_data_size = sizeof(RawVideoDemuxerContext), + .read_header = rawvideo_read_header, + .read_packet = rawvideo_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "yuv10", + .raw_codec_id = AV_CODEC_ID_V210X, + .priv_class = &v210_demuxer_class, +}; +#endif // CONFIG_V210X_DEMUXER From e35b70ab278474feb7649ed1e339ad7626762680 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Wed, 22 Dec 2021 23:08:14 +0800 Subject: [PATCH 763/894] avformat: remove unused v210.c Signed-off-by: Limin Wang --- libavformat/v210.c | 123 --------------------------------------------- 1 file changed, 123 deletions(-) delete mode 100644 libavformat/v210.c diff --git a/libavformat/v210.c b/libavformat/v210.c deleted file mode 100644 index 24f71d4014..0000000000 --- a/libavformat/v210.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Raw v210 video demuxer - * Copyright (c) 2015 Tiancheng "Timothy" Gu - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/imgutils.h" -#include "libavutil/parseutils.h" -#include "libavutil/pixdesc.h" -#include "libavutil/opt.h" -#include "internal.h" -#include "avformat.h" - -typedef struct V210DemuxerContext { - const AVClass *class; /**< Class for private options. */ - int width, height; /**< Integers describing video size, set by a private option. */ - AVRational framerate; /**< AVRational describing framerate, set by a private option. */ -} V210DemuxerContext; - -// v210 frame width is padded to multiples of 48 -#define GET_PACKET_SIZE(w, h) (((w + 47) / 48) * 48 * h * 8 / 3) - -static int v210_read_header(AVFormatContext *ctx) -{ - V210DemuxerContext *s = ctx->priv_data; - AVStream *st; - int ret; - - st = avformat_new_stream(ctx, NULL); - if (!st) - return AVERROR(ENOMEM); - - st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - - st->codecpar->codec_id = ctx->iformat->raw_codec_id; - - avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); - - ret = av_image_check_size(s->width, s->height, 0, ctx); - if (ret < 0) - return ret; - st->codecpar->width = s->width; - st->codecpar->height = s->height; - st->codecpar->format = ctx->iformat->raw_codec_id == AV_CODEC_ID_V210 ? - AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV422P16; - ctx->packet_size = GET_PACKET_SIZE(s->width, s->height); - st->codecpar->bit_rate = av_rescale_q(ctx->packet_size, - (AVRational){8,1}, st->time_base); - - return 0; -} - - -static int v210_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - int ret; - - ret = av_get_packet(s->pb, pkt, s->packet_size); - pkt->pts = pkt->dts = pkt->pos / s->packet_size; - - pkt->stream_index = 0; - if (ret < 0) - return ret; - return 0; -} - -#define OFFSET(x) offsetof(V210DemuxerContext, x) -#define DEC AV_OPT_FLAG_DECODING_PARAM -static const AVOption v210_options[] = { - { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, - { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC }, - { NULL }, -}; - -static const AVClass v210_demuxer_class = { - .class_name = "v210(x) demuxer", - .item_name = av_default_item_name, - .option = v210_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -#if CONFIG_V210_DEMUXER -const AVInputFormat ff_v210_demuxer = { - .name = "v210", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .priv_data_size = sizeof(V210DemuxerContext), - .read_header = v210_read_header, - .read_packet = v210_read_packet, - .flags = AVFMT_GENERIC_INDEX, - .extensions = "v210", - .raw_codec_id = AV_CODEC_ID_V210, - .priv_class = &v210_demuxer_class, -}; -#endif // CONFIG_V210_DEMUXER - -#if CONFIG_V210X_DEMUXER -const AVInputFormat ff_v210x_demuxer = { - .name = "v210x", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .priv_data_size = sizeof(V210DemuxerContext), - .read_header = v210_read_header, - .read_packet = v210_read_packet, - .flags = AVFMT_GENERIC_INDEX, - .extensions = "yuv10", - .raw_codec_id = AV_CODEC_ID_V210X, - .priv_class = &v210_demuxer_class, -}; -#endif // CONFIG_V210X_DEMUXER From cb87a3b137d26d8af9a96b8bb60294a1668857a4 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 02:57:44 -0600 Subject: [PATCH 764/894] swscale/output: template-ize yuv2nv12cX 10-bit and 16-bit cases Fixes incorrect big-endian output introduced in 88d804b7ffa20caab2e8e2809da974c41f7fd8fc Avoids making the filter-time BE check more expensive --- libswscale/output.c | 48 ++++++++++++++++++++---- tests/ref/fate/filter-pixdesc-p210be | 2 +- tests/ref/fate/filter-pixdesc-p216be | 2 +- tests/ref/fate/filter-pixdesc-p410be | 2 +- tests/ref/fate/filter-pixdesc-p416be | 2 +- tests/ref/fate/filter-pixfmts-copy | 8 ++-- tests/ref/fate/filter-pixfmts-crop | 8 ++-- tests/ref/fate/filter-pixfmts-field | 8 ++-- tests/ref/fate/filter-pixfmts-fieldorder | 8 ++-- tests/ref/fate/filter-pixfmts-hflip | 8 ++-- tests/ref/fate/filter-pixfmts-il | 8 ++-- tests/ref/fate/filter-pixfmts-null | 8 ++-- tests/ref/fate/filter-pixfmts-scale | 8 ++-- tests/ref/fate/filter-pixfmts-transpose | 4 +- tests/ref/fate/filter-pixfmts-vflip | 8 ++-- 15 files changed, 83 insertions(+), 49 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index 4b4b186be9..e7cea49096 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -180,17 +180,18 @@ yuv2planeX_16_c_template(const int16_t *filter, int filterSize, } } -static void yuv2p016cX_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, +static av_always_inline void +yuv2nv12cX_16_c_template(int big_endian, const uint8_t *chrDither, const int16_t *chrFilter, int chrFilterSize, const int16_t **chrUSrc, const int16_t **chrVSrc, - uint8_t *dest8, int chrDstW) + uint8_t *dest8, int chrDstW, int output_bits) { uint16_t *dest = (uint16_t*)dest8; const int32_t **uSrc = (const int32_t **)chrUSrc; const int32_t **vSrc = (const int32_t **)chrVSrc; int shift = 15; - int big_endian = dstFormat == AV_PIX_FMT_P016BE; int i, j; + av_assert0(output_bits == 16); for (i = 0; i < chrDstW; i++) { int u = 1 << (shift - 1); @@ -367,6 +368,7 @@ static void yuv2planeX_ ## bits ## BE_LE ## _c(const int16_t *filter, int filter filterSize, (const typeX_t **) src, \ (uint16_t *) dest, dstW, is_be, bits); \ } + yuv2NBPS( 9, BE, 1, 10, int16_t) yuv2NBPS( 9, LE, 0, 10, int16_t) yuv2NBPS(10, BE, 1, 10, int16_t) @@ -378,6 +380,23 @@ yuv2NBPS(14, LE, 0, 10, int16_t) yuv2NBPS(16, BE, 1, 16, int32_t) yuv2NBPS(16, LE, 0, 16, int32_t) + +static void yuv2nv12cX_16LE_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + yuv2nv12cX_16_c_template(0, chrDither, chrFilter, chrFilterSize, chrUSrc, chrVSrc, dest8, chrDstW, 16); +} + +static void yuv2nv12cX_16BE_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + yuv2nv12cX_16_c_template(1, chrDither, chrFilter, chrFilterSize, chrUSrc, chrVSrc, dest8, chrDstW, 16); +} + static void yuv2planeX_8_c(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset) @@ -477,14 +496,13 @@ static void yuv2p010lX_c(const int16_t *filter, int filterSize, } } -static void yuv2p010cX_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, +static void yuv2p010cX_c(int big_endian, const uint8_t *chrDither, const int16_t *chrFilter, int chrFilterSize, const int16_t **chrUSrc, const int16_t **chrVSrc, uint8_t *dest8, int chrDstW) { uint16_t *dest = (uint16_t*)dest8; int shift = 17; - int big_endian = dstFormat == AV_PIX_FMT_P010BE; int i, j; for (i = 0; i < chrDstW; i++) { @@ -529,6 +547,22 @@ static void yuv2p010lX_BE_c(const int16_t *filter, int filterSize, yuv2p010lX_c(filter, filterSize, src, (uint16_t*)dest, dstW, 1); } +static void yuv2p010cX_LE_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + yuv2p010cX_c(0, chrDither, chrFilter, chrFilterSize, chrUSrc, chrVSrc, dest8, chrDstW); +} + +static void yuv2p010cX_BE_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + yuv2p010cX_c(1, chrDither, chrFilter, chrFilterSize, chrUSrc, chrVSrc, dest8, chrDstW); +} + #undef output_pixel @@ -2568,14 +2602,14 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, dstFormat == AV_PIX_FMT_P410LE || dstFormat == AV_PIX_FMT_P410BE) { *yuv2plane1 = isBE(dstFormat) ? yuv2p010l1_BE_c : yuv2p010l1_LE_c; *yuv2planeX = isBE(dstFormat) ? yuv2p010lX_BE_c : yuv2p010lX_LE_c; - *yuv2nv12cX = yuv2p010cX_c; + *yuv2nv12cX = isBE(dstFormat) ? yuv2p010cX_BE_c : yuv2p010cX_LE_c; } else if (is16BPS(dstFormat)) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE || dstFormat == AV_PIX_FMT_P216LE || dstFormat == AV_PIX_FMT_P216BE || dstFormat == AV_PIX_FMT_P416LE || dstFormat == AV_PIX_FMT_P416BE) { - *yuv2nv12cX = yuv2p016cX_c; + *yuv2nv12cX = isBE(dstFormat) ? yuv2nv12cX_16BE_c : yuv2nv12cX_16LE_c; } } else if (isNBPS(dstFormat)) { if (desc->comp[0].depth == 9) { diff --git a/tests/ref/fate/filter-pixdesc-p210be b/tests/ref/fate/filter-pixdesc-p210be index b7d15ff93d..9ff89d14a0 100644 --- a/tests/ref/fate/filter-pixdesc-p210be +++ b/tests/ref/fate/filter-pixdesc-p210be @@ -1 +1 @@ -pixdesc-p210be 9f3465e388d91beeb5cb7fe0011c5a67 +pixdesc-p210be 016fd90989d14914bbbcc7dc2968bef0 diff --git a/tests/ref/fate/filter-pixdesc-p216be b/tests/ref/fate/filter-pixdesc-p216be index 657136996a..932c5b2708 100644 --- a/tests/ref/fate/filter-pixdesc-p216be +++ b/tests/ref/fate/filter-pixdesc-p216be @@ -1 +1 @@ -pixdesc-p216be db5cabe6e5f1814a6d20e8398aec4785 +pixdesc-p216be d95084fa0758169851f57455a9624a2e diff --git a/tests/ref/fate/filter-pixdesc-p410be b/tests/ref/fate/filter-pixdesc-p410be index 26ff981622..27de3ee0bb 100644 --- a/tests/ref/fate/filter-pixdesc-p410be +++ b/tests/ref/fate/filter-pixdesc-p410be @@ -1 +1 @@ -pixdesc-p410be 85671676fa52d0350c918f45417f3c64 +pixdesc-p410be 33d7e8e5d6a85cc22fcbf0c12c7bafd0 diff --git a/tests/ref/fate/filter-pixdesc-p416be b/tests/ref/fate/filter-pixdesc-p416be index 5a23be5d72..f67b553d42 100644 --- a/tests/ref/fate/filter-pixdesc-p416be +++ b/tests/ref/fate/filter-pixdesc-p416be @@ -1 +1 @@ -pixdesc-p416be a7d8a859ce47c3860e0fee31539a84b0 +pixdesc-p416be 6a4b1b2fc8435acfc82312109f13bc58 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index b090739bd2..f06fa1574e 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -63,13 +63,13 @@ p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b -p210be 6df2a72ee297e53f9ac7f96acf0ef5d5 +p210be 847e9c6e292b17349e69570829252b3e p210le c06e4b76cf504e908128081f92b60ce2 -p216be 01d10b0d17c9f575b512dff36623a85b +p216be f5009974fc1cd5d552705eeb52de35d9 p216le 2f634e1a3cd5c9c122e0f2ebadb3503d -p410be d9af5b8126ea7457edaf0c90ad0cb2b7 +p410be 7c2509d2df4bbb199ab653ebb6dce61e p410le 527761e1f4381007044679710a352ecc -p416be fc5c1c45567de4a6bc9dbc8eef30116d +p416be fd828e966d45ae908f5d2d4b3349b816 p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index 93353ad16a..8b26ab9c53 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -61,13 +61,13 @@ p010be 8b2de2eb6b099bbf355bfc55a0694ddc p010le 373b50c766dfd0a8e79c9a73246d803a p016be 8b2de2eb6b099bbf355bfc55a0694ddc p016le 373b50c766dfd0a8e79c9a73246d803a -p210be b75f0e53a245e49af955fe210fc31bb8 +p210be 2947f43774352ef61f9e83777548c7c5 p210le 74fcd5a32eee687eebe002c884103963 -p216be 89cb3a4bd44ba624c1395e7ea6998dde +p216be 41351128eaf636041c8987698730391a p216le e56f5e5b0d4460d56f27a5df8a4a1462 -p410be 37e56737c2421aa59a33c57423d58616 +p410be e17c78ff059363177548412e6ab4e65f p410le 75f910c7282d8065d97f502ba974c481 -p416be 13b2dc247bdb0ab7e5532f75048f5a2c +p416be 52f08b8a56a09d6e954c2eab6cf24d99 p416le ecb78b327ea5cfe1fff82945c1fca310 pal8 1f2cdc8e718f95c875dbc1034a688bfb rgb0 736646b70dd9a0be22b8da8041e35035 diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field index bcd1a0a45b..c4838d1446 100644 --- a/tests/ref/fate/filter-pixfmts-field +++ b/tests/ref/fate/filter-pixfmts-field @@ -63,13 +63,13 @@ p010be a0311a09bba7383553267d2b3b9c075e p010le ee09a18aefa3ebe97715b3a7312cb8ff p016be a0311a09bba7383553267d2b3b9c075e p016le ee09a18aefa3ebe97715b3a7312cb8ff -p210be 341db7c98afd2767d48cdd72e224df2f +p210be 58d46f566ab28e3bcfb715c7aa53cf58 p210le 8d68f7655a3d76f2f8436bd25beb3973 -p216be 0dde930860e940dced179884c359f720 +p216be dd1f3e0bb5c49775a598ab29802fc268 p216le b573c0473a1368813d077487cc9bce0e -p410be 9e9a812b74854226271c5f7dc18c37b7 +p410be 658fd0d92eb327cbd562abafc8694db7 p410le c981188c7fd9f32988a9f4732303f82b -p416be 203203e6788a80b52d2ca6ba629beb9c +p416be 66616bf2320464b5e9b6372d48b6b9a9 p416le 1039b97bbe42ef0af1bc46d2c0fc819e pal8 0658c18dcd8d052d59dfbe23f5b368d9 rgb0 ca3fa6e865b91b3511c7f2bf62830059 diff --git a/tests/ref/fate/filter-pixfmts-fieldorder b/tests/ref/fate/filter-pixfmts-fieldorder index 761ef422b5..32c06bae4c 100644 --- a/tests/ref/fate/filter-pixfmts-fieldorder +++ b/tests/ref/fate/filter-pixfmts-fieldorder @@ -55,13 +55,13 @@ grayf32be 1aa7960131f880c54fe3c77f13448674 grayf32le 4029ac9d197f255794c1b9e416520fc7 nv24 4fdbef26042c77f012df114e666efdb2 nv42 59608290fece913e6b7d61edf581a529 -p210be 82958903f553e9d2d91549bd44559a5a +p210be ca2ce2c25db43dcd14729b2a72a7c604 p210le 755363012d8801b96ead2e8b1b4d2ab8 -p216be 7159f11beb9138932f8d60b95efe96dc +p216be 17741c0cdb65914ad13c5114121a175f p216le c0c888ab7bde56638732344076b3b2ba -p410be 411f89fadbee1ca43d2918eba583bea5 +p410be b6d65b820198ca6ff0103d9794727792 p410le 2771dd3ae54a439921f51c29e79b6799 -p416be de6b84bd524e8fcfc251634cae416069 +p416be a0f8b5acad8fafc45fc7b2275fac1d84 p416le 2e73af44eb933580da59981176848dcc rgb0 2e3d8c91c7a83d451593dfd06607ff39 rgb24 b82577f8215d3dc2681be60f1da247af diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index 1fc26b9fb5..4d3efe3cdc 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -61,13 +61,13 @@ p010be 744b13e44d39e1ff7588983fa03e0101 p010le a50b160346ab94f55a425065b57006f0 p016be 744b13e44d39e1ff7588983fa03e0101 p016le a50b160346ab94f55a425065b57006f0 -p210be 174cdf99f18658724e269bf38d2b653b +p210be 6f5a76d6467b86d55fe5589d3af8a7ea p210le b6982912b2376371edea4fccf99fe40c -p216be c58f03c6668ab0fbc3ee1a2da051e28c +p216be c1b58f61cd6df9cf01c3086786fb8a69 p216le 1f5213bebf4c99634f57290f5ad99c0d -p410be aa40aa32be7aa353252bac70b5edc175 +p410be 2e06214ea84595aa1294239b0f1e900f p410le 1143c811c383e4461b1192dca0c74246 -p416be 8863e9156ee7edcb6b9e6ac01a2e338c +p416be da6807d924b63a54b804d32e427524bf p416le a42b88cabc4395aa0bf1bcbbc876f48f pal8 5b7c77d99817b4f52339742a47de7797 rgb0 0092452f37d73da20193265ace0b7d57 diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il index 7e7f057afa..4623f2420c 100644 --- a/tests/ref/fate/filter-pixfmts-il +++ b/tests/ref/fate/filter-pixfmts-il @@ -63,13 +63,13 @@ p010be 3df51286ef66b53e3e283dbbab582263 p010le eadcd8241e97e35b2b47d5eb2eaea6cd p016be 3df51286ef66b53e3e283dbbab582263 p016le eadcd8241e97e35b2b47d5eb2eaea6cd -p210be 4992fe87c600dfb177b1e2e6aa0f922c +p210be 29ec4e8912d456cd15203a96487c42e8 p210le c695064fb9f2cc4e35957d4d649cc281 -p216be 98b73479f0ea9843768c162c449c3ac5 +p216be ad85bdc59755608602608a9438bb82ea p216le 77757390da383a90981e461d128d8789 -p410be a7183a01888b47a4d9f3672073c7ea7d +p410be 2128861337e660232e6fb664cc4de3e6 p410le 6cf3a3e199b327f4f013e0346410d7a8 -p416be 4dc4aebf18e09e8f8b49db90ae5ec127 +p416be 47dec75cefeb6220be7731bc25b7be9c p416le 4990b51ff889d9ee23e68997f81c09f1 rgb0 cfaf68671e43248267d8cd50cae8c13f rgb24 88894f608cf33ba310f21996748d77a7 diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index b090739bd2..f06fa1574e 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -63,13 +63,13 @@ p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b -p210be 6df2a72ee297e53f9ac7f96acf0ef5d5 +p210be 847e9c6e292b17349e69570829252b3e p210le c06e4b76cf504e908128081f92b60ce2 -p216be 01d10b0d17c9f575b512dff36623a85b +p216be f5009974fc1cd5d552705eeb52de35d9 p216le 2f634e1a3cd5c9c122e0f2ebadb3503d -p410be d9af5b8126ea7457edaf0c90ad0cb2b7 +p410be 7c2509d2df4bbb199ab653ebb6dce61e p410le 527761e1f4381007044679710a352ecc -p416be fc5c1c45567de4a6bc9dbc8eef30116d +p416be fd828e966d45ae908f5d2d4b3349b816 p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index a5a4ac4cba..43074b84a7 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -63,13 +63,13 @@ p010be 1d6726d94bf1385996a9a9840dd0e878 p010le 4b316f2b9e18972299beb73511278fa8 p016be 31e204018cbb53f8988c4e1174ea8ce9 p016le d5afe557f492a09317e525d7cb782f5b -p210be 42be1e97427247317444afa836969667 +p210be 2cc6dfcf5e006c8ed5238988a06fd45e p210le 04efb8f14a9d98417af40954a06aa187 -p216be caa0268d0f6779343a4432b6bc832c5b +p216be 2f649a226812c8e5a553c4e22d301684 p216le c8f65811f717a12706a598561c6df46d -p410be f580b8dcf5a826c94258eeba837fd874 +p410be 354cd1324ad382df1a3d573833323cce p410le 90fdd95ec4482c127d98307550a885c6 -p416be a1242f80d32705a757f4d3553542ae1f +p416be aa54294859a8e6cb2c9cf64d343fdb60 p416le d91a0858ea8d2cf1ed29f179c9ad9666 pal8 29e10892009b2cfe431815ec3052ed3b rgb0 fbd27e98154efb7535826afed41e9bb0 diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose index dc3a0628ee..922666cf95 100644 --- a/tests/ref/fate/filter-pixfmts-transpose +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -61,9 +61,9 @@ p010be ad0de2cc9bff81688b182a870fcf7000 p010le e7ff5143595021246733ce6bd0a769e8 p016be ad0de2cc9bff81688b182a870fcf7000 p016le e7ff5143595021246733ce6bd0a769e8 -p410be 171453dc34dd3c77659914e2202c5aa6 +p410be 8b3e0ccb31b6a20ff00a29253fb2dec3 p410le 4e5f78dfccda9a6387e81354a56a033a -p416be ff09601f127101a8ce8997b9ae0fd6bf +p416be 350a90bda53349435d89ec13533726b7 p416le 7bb46e2aec65669a27502ec452941237 rgb0 31ea5da7fe779c6ea0a33f1d28aad918 rgb24 47654cabaaad79170b90afd5a02161dd diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 7736e372ad..3a53bb5837 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -63,13 +63,13 @@ p010be 06e9354b6e0e38ba41736352cedc0bd5 p010le fd18d322bffbf5816902c13102872e22 p016be 06e9354b6e0e38ba41736352cedc0bd5 p016le fd18d322bffbf5816902c13102872e22 -p210be 328b09bb0c70571617901322b4194023 +p210be ca886ab2b3ea5c153f1954b3709f7249 p210le d71c2d4e483030ffd87fa6a68c83fce0 -p216be e4ab026532db1dfee38cedef384e605b +p216be 7f268f755ed02592b3a49fd5f7bd48bb p216le 2c0a660762527706799c4705ca50a9c5 -p410be 637fb064c2ce173de5cf431aa9267914 +p410be 4c603e4464ed3f34cc432b4d1f912082 p410le 849308a1cdf41e055019cf311d1b2201 -p416be 8e9cf1b695c0a33b6094dd6c7b3722d9 +p416be 7e7657ab40cf953351a14ea76e296519 p416le 0991d7fff4e2caf36be219ecdd9619d4 pal8 450b0155d0f2d5628bf95a442db5f817 rgb0 56a7ea69541bcd27bef6a5615784722b From e5d83463c8745c1b9d8ce83d00a5856a4dd19ceb Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 03:19:11 -0600 Subject: [PATCH 765/894] swscale: introduce isDataInHighBits --- libswscale/swscale_internal.h | 19 +++++++++++++++++++ libswscale/tests/pixdesc_query.c | 1 + tests/ref/fate/sws-pixdesc-query | 12 ++++++++++++ 3 files changed, 32 insertions(+) diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 64aa0b9804..b4acaceebd 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -892,6 +892,25 @@ static av_always_inline int usePal(enum AVPixelFormat pix_fmt) } } +/* + * Identity formats where the data is in the high bits, and the low bits are shifted away. + */ +static av_always_inline int isDataInHighBits(enum AVPixelFormat pix_fmt) +{ + int i; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) + return 0; + for (i = 0; i < desc->nb_components; i++) { + if (!desc->comp[i].shift) + return 0; + if ((desc->comp[i].shift + desc->comp[i].depth) & 0x7) + return 0; + } + return 1; +} + extern const uint64_t ff_dither4[2]; extern const uint64_t ff_dither8[2]; diff --git a/libswscale/tests/pixdesc_query.c b/libswscale/tests/pixdesc_query.c index f6dd8bae68..dce2e50577 100644 --- a/libswscale/tests/pixdesc_query.c +++ b/libswscale/tests/pixdesc_query.c @@ -45,6 +45,7 @@ static const struct { {"PackedRGB", isPackedRGB}, {"PlanarRGB", isPlanarRGB}, {"usePal", usePal}, + {"DataInHighBits", isDataInHighBits}, }; static int cmp_str(const void *a, const void *b) diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query index 553c039061..a17284784f 100644 --- a/tests/ref/fate/sws-pixdesc-query +++ b/tests/ref/fate/sws-pixdesc-query @@ -952,3 +952,15 @@ usePal: rgb4_byte rgb8 +DataInHighBits: + p010be + p010le + p210be + p210le + p410be + p410le + xyz12be + xyz12le + y210be + y210le + From cf9e8cb52f413ec9cf82b8934db1d5f9c7fbb975 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 03:28:21 -0600 Subject: [PATCH 766/894] swscale/output: use isSemiPlanarYUV for 16-bit case --- libswscale/output.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index e7cea49096..e43eb7835e 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -2606,9 +2606,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, } else if (is16BPS(dstFormat)) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; - if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE || - dstFormat == AV_PIX_FMT_P216LE || dstFormat == AV_PIX_FMT_P216BE || - dstFormat == AV_PIX_FMT_P416LE || dstFormat == AV_PIX_FMT_P416BE) { + if (isSemiPlanarYUV(dstFormat)) { *yuv2nv12cX = isBE(dstFormat) ? yuv2nv12cX_16BE_c : yuv2nv12cX_16LE_c; } } else if (isNBPS(dstFormat)) { From bb4f19f2a27ec2170dee852f7f307fcbc51faba9 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 03:29:04 -0600 Subject: [PATCH 767/894] swscale/output: use isDataInHighBits for 10-bit case This code will need fleshing-out (probably templating) if we ever add e.g. a P012 format. --- libswscale/output.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index e43eb7835e..7cedb145aa 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -2597,9 +2597,8 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, enum AVPixelFormat dstFormat = c->dstFormat; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); - if (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P010BE || - dstFormat == AV_PIX_FMT_P210LE || dstFormat == AV_PIX_FMT_P210BE || - dstFormat == AV_PIX_FMT_P410LE || dstFormat == AV_PIX_FMT_P410BE) { + if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) { + av_assert0(desc->comp[0].depth == 10); *yuv2plane1 = isBE(dstFormat) ? yuv2p010l1_BE_c : yuv2p010l1_LE_c; *yuv2planeX = isBE(dstFormat) ? yuv2p010lX_BE_c : yuv2p010lX_LE_c; *yuv2nv12cX = isBE(dstFormat) ? yuv2p010cX_BE_c : yuv2p010cX_LE_c; From f8e284be69d6eae480c6d7291763b840959b7bf1 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 03:49:27 -0600 Subject: [PATCH 768/894] swscale: introduce isSwappedChroma --- libswscale/swscale_internal.h | 19 +++++++++++++++++++ libswscale/tests/pixdesc_query.c | 1 + tests/ref/fate/sws-pixdesc-query | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index b4acaceebd..3a78d95ba6 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -911,6 +911,25 @@ static av_always_inline int isDataInHighBits(enum AVPixelFormat pix_fmt) return 1; } +/* + * Identity formats where the chroma planes are swapped (CrCb order). + */ +static av_always_inline int isSwappedChroma(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + if (!isYUV(pix_fmt)) + return 0; + if ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) && desc->nb_components < 4) + return 0; + if (desc->nb_components < 3) + return 0; + if (!isPlanarYUV(pix_fmt) || isSemiPlanarYUV(pix_fmt)) + return desc->comp[1].offset > desc->comp[2].offset; + else + return desc->comp[1].plane > desc->comp[2].plane; +} + extern const uint64_t ff_dither4[2]; extern const uint64_t ff_dither8[2]; diff --git a/libswscale/tests/pixdesc_query.c b/libswscale/tests/pixdesc_query.c index dce2e50577..eb793877a0 100644 --- a/libswscale/tests/pixdesc_query.c +++ b/libswscale/tests/pixdesc_query.c @@ -46,6 +46,7 @@ static const struct { {"PlanarRGB", isPlanarRGB}, {"usePal", usePal}, {"DataInHighBits", isDataInHighBits}, + {"SwappedChroma", isSwappedChroma}, }; static int cmp_str(const void *a, const void *b) diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query index a17284784f..76104bc5a6 100644 --- a/tests/ref/fate/sws-pixdesc-query +++ b/tests/ref/fate/sws-pixdesc-query @@ -964,3 +964,8 @@ DataInHighBits: y210be y210le +SwappedChroma: + nv21 + nv42 + yvyu422 + From cb3a6cc08275b0251edfc346f8d7afc595555e52 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 03:52:11 -0600 Subject: [PATCH 769/894] swscale/output: use isSemiPlanarYUV for NV12/21/24/42 case --- libswscale/output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index 7cedb145aa..90f5efa16e 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -2632,8 +2632,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, } else { *yuv2plane1 = yuv2plane1_8_c; *yuv2planeX = yuv2planeX_8_c; - if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21 || - dstFormat == AV_PIX_FMT_NV24 || dstFormat == AV_PIX_FMT_NV42) + if (isSemiPlanarYUV(dstFormat)) *yuv2nv12cX = yuv2nv12cX_c; } From df9180d8a072ac86ced8930a5d6bd0e61e314749 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 03:52:33 -0600 Subject: [PATCH 770/894] swscale/output: use isSwappedChroma --- libswscale/output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index 90f5efa16e..773f3ce059 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -429,8 +429,7 @@ static void yuv2nv12cX_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, { int i; - if (dstFormat == AV_PIX_FMT_NV12 || - dstFormat == AV_PIX_FMT_NV24) + if (!isSwappedChroma(dstFormat)) for (i=0; i Date: Thu, 23 Dec 2021 04:11:56 -0600 Subject: [PATCH 771/894] lavfi/drawutils: move BE check out of loop --- libavfilter/drawutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 88218b913f..79570e71da 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -89,6 +89,8 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) if (!desc || !desc->name) return AVERROR(EINVAL); + if (desc->flags & AV_PIX_FMT_FLAG_BE) + return AVERROR(ENOSYS); if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) return AVERROR(ENOSYS); if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P010BE || format == AV_PIX_FMT_P016LE || format == AV_PIX_FMT_P016BE) @@ -101,8 +103,6 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) /* for now, only 8-16 bits formats */ if (c->depth < 8 || c->depth > 16) return AVERROR(ENOSYS); - if (desc->flags & AV_PIX_FMT_FLAG_BE) - return AVERROR(ENOSYS); if (c->plane >= MAX_PLANES) return AVERROR(ENOSYS); /* strange interleaving */ From 186e931f74bbc368e576965365006de8b3433cbf Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 04:13:37 -0600 Subject: [PATCH 772/894] lavfi/drawutils: remove redundant BE format checks We already explicitly don't support big-endian in general --- libavfilter/drawutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 79570e71da..6b46f5803d 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -93,7 +93,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) return AVERROR(ENOSYS); if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) return AVERROR(ENOSYS); - if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P010BE || format == AV_PIX_FMT_P016LE || format == AV_PIX_FMT_P016BE) + if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P016LE) return AVERROR(ENOSYS); if (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || format == AV_PIX_FMT_YUVJ444P || format == AV_PIX_FMT_YUVJ411P || format == AV_PIX_FMT_YUVJ440P) From 5018103fa32cdf5725e8e1309b9ddf89958910b1 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 15:12:44 -0600 Subject: [PATCH 773/894] lavfi/drawutils: reject shift-packed formats Disables x2bgr10/x2rgb10 (which did not behave correctly before). --- libavfilter/drawutils.c | 3 +++ tests/ref/fate/filter-pixfmts-pad | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 6b46f5803d..0965afb03e 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -105,6 +105,9 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) return AVERROR(ENOSYS); if (c->plane >= MAX_PLANES) return AVERROR(ENOSYS); + /* data must either be in the high or low bits, never middle */ + if (c->shift && ((c->shift + c->depth) & 0x7)) + return AVERROR(ENOSYS); /* strange interleaving */ if (pixelstep[c->plane] != 0 && pixelstep[c->plane] != c->step) diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 1362d198b4..74981cd6c1 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -32,8 +32,6 @@ p416le 6db094f8d7d27d7299bf9496ad66e2e0 rgb0 78d500c8361ab6423a4826a00268c908 rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 -x2bgr10le d4aff89f5e15ccbb1812f319874ed444 -x2rgb10le a0c5925bd56b6f85f918c4e9fb93e90e xyz12le 85abf80b77a9236a76ba0b00fcbdea2d ya16le 940fafa240b9916de5f73cb20a552f24 ya8 5fc0f471207ddf7aa01b07027d56b672 From e24b71add534b44909519dcd0b5eaa0c9e9c9bbc Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 19:19:28 -0600 Subject: [PATCH 774/894] lavfi/drawutils: reimplement ff_fill_rgba_map without hardcoding the list Same outputs, but computed instead of statically known, so new formats will be supported more easily. Asserts in place to ensure we update this if we add anything incompatible with its logic. --- libavfilter/drawutils.c | 81 ++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 0965afb03e..e4d6ddcf4c 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -21,6 +21,7 @@ #include +#include "libavutil/avassert.h" #include "libavutil/avutil.h" #include "libavutil/colorspace.h" #include "libavutil/intreadwrite.h" @@ -32,50 +33,46 @@ enum { RED = 0, GREEN, BLUE, ALPHA }; int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt) { - switch (pix_fmt) { - case AV_PIX_FMT_0RGB: - case AV_PIX_FMT_ARGB: rgba_map[ALPHA] = 0; rgba_map[RED ] = 1; rgba_map[GREEN] = 2; rgba_map[BLUE ] = 3; break; - case AV_PIX_FMT_0BGR: - case AV_PIX_FMT_ABGR: rgba_map[ALPHA] = 0; rgba_map[BLUE ] = 1; rgba_map[GREEN] = 2; rgba_map[RED ] = 3; break; - case AV_PIX_FMT_RGB48LE: - case AV_PIX_FMT_RGB48BE: - case AV_PIX_FMT_RGBA64BE: - case AV_PIX_FMT_RGBA64LE: - case AV_PIX_FMT_RGB0: - case AV_PIX_FMT_RGBA: - case AV_PIX_FMT_RGB24: rgba_map[RED ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break; - case AV_PIX_FMT_BGR48LE: - case AV_PIX_FMT_BGR48BE: - case AV_PIX_FMT_BGRA64BE: - case AV_PIX_FMT_BGRA64LE: - case AV_PIX_FMT_BGRA: - case AV_PIX_FMT_BGR0: - case AV_PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break; - case AV_PIX_FMT_GBRP9LE: - case AV_PIX_FMT_GBRP9BE: - case AV_PIX_FMT_GBRP10LE: - case AV_PIX_FMT_GBRP10BE: - case AV_PIX_FMT_GBRP12LE: - case AV_PIX_FMT_GBRP12BE: - case AV_PIX_FMT_GBRP14LE: - case AV_PIX_FMT_GBRP14BE: - case AV_PIX_FMT_GBRP16LE: - case AV_PIX_FMT_GBRP16BE: - case AV_PIX_FMT_GBRAP: - case AV_PIX_FMT_GBRAP10LE: - case AV_PIX_FMT_GBRAP10BE: - case AV_PIX_FMT_GBRAP12LE: - case AV_PIX_FMT_GBRAP12BE: - case AV_PIX_FMT_GBRAP16LE: - case AV_PIX_FMT_GBRAP16BE: - case AV_PIX_FMT_GBRPF32LE: - case AV_PIX_FMT_GBRPF32BE: - case AV_PIX_FMT_GBRAPF32LE: - case AV_PIX_FMT_GBRAPF32BE: - case AV_PIX_FMT_GBRP: rgba_map[GREEN] = 0; rgba_map[BLUE ] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break; - default: /* unsupported */ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) return AVERROR(EINVAL); + if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) + return AVERROR(EINVAL); + av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)); + if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) { + rgba_map[RED] = desc->comp[0].plane; + rgba_map[GREEN] = desc->comp[1].plane; + rgba_map[BLUE] = desc->comp[2].plane; + rgba_map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3; + } else { + int had0 = 0; + unsigned depthb = 0; + unsigned i; + for (i = 0; i < desc->nb_components; i++) { + /* all components must have same depth in bytes */ + unsigned db = (desc->comp[i].depth + 7) / 8; + unsigned pos = desc->comp[i].offset / db; + if (depthb && (depthb != db)) + return AVERROR(ENOSYS); + + if (desc->comp[i].offset % db) + return AVERROR(ENOSYS); + + had0 |= pos == 0; + rgba_map[i] = pos; + } + + if (desc->nb_components == 3) + rgba_map[ALPHA] = had0 ? 3 : 0; } + + av_assert0(rgba_map[RED] != rgba_map[GREEN]); + av_assert0(rgba_map[GREEN] != rgba_map[BLUE]); + av_assert0(rgba_map[BLUE] != rgba_map[RED]); + av_assert0(rgba_map[RED] != rgba_map[ALPHA]); + av_assert0(rgba_map[GREEN] != rgba_map[ALPHA]); + av_assert0(rgba_map[BLUE] != rgba_map[ALPHA]); + return 0; } From f00079b25c44d6b9f01bb3688bfd1cd49abefac8 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 19:28:35 -0600 Subject: [PATCH 775/894] lavfi/drawutils: ensure we don't allow mixed-byte-depth formats These could be hazardous because of FFDrawColor's union --- libavfilter/drawutils.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index e4d6ddcf4c..99c124822d 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -83,6 +83,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) unsigned i, nb_planes = 0; int pixelstep[MAX_PLANES] = { 0 }; int full_range = 0; + int depthb = 0; if (!desc || !desc->name) return AVERROR(EINVAL); @@ -96,6 +97,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) format == AV_PIX_FMT_YUVJ411P || format == AV_PIX_FMT_YUVJ440P) full_range = 1; for (i = 0; i < desc->nb_components; i++) { + int db; c = &desc->comp[i]; /* for now, only 8-16 bits formats */ if (c->depth < 8 || c->depth > 16) @@ -105,6 +107,11 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) /* data must either be in the high or low bits, never middle */ if (c->shift && ((c->shift + c->depth) & 0x7)) return AVERROR(ENOSYS); + /* mixed >8 and <=8 depth */ + db = (c->depth + 7) / 8; + if (depthb && (depthb != db)) + return AVERROR(ENOSYS); + depthb = db; /* strange interleaving */ if (pixelstep[c->plane] != 0 && pixelstep[c->plane] != c->step) From f320722eb5e3af84860063827636369115094ab5 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 19:48:24 -0600 Subject: [PATCH 776/894] lavfi/drawutils: ensure we can't overflow a component --- libavfilter/drawutils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 99c124822d..bcdb669bd3 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -112,6 +112,8 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) if (depthb && (depthb != db)) return AVERROR(ENOSYS); depthb = db; + if (db * (c->offset + 1) > 16) + return AVERROR(ENOSYS); /* strange interleaving */ if (pixelstep[c->plane] != 0 && pixelstep[c->plane] != c->step) From f67bd3a8254f50676dee037a0c0b31e4148c1a85 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 20:56:50 -0600 Subject: [PATCH 777/894] lavfi/drawutils: ensure we don't support formats with non-pixel-sized offsets --- libavfilter/drawutils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index bcdb669bd3..5308fcbc0f 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -114,6 +114,8 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) depthb = db; if (db * (c->offset + 1) > 16) return AVERROR(ENOSYS); + if (c->offset % db) + return AVERROR(ENOSYS); /* strange interleaving */ if (pixelstep[c->plane] != 0 && pixelstep[c->plane] != c->step) From 66343e46cfb1bd85dcecc066b9bf444823bd0d82 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 20:06:29 -0600 Subject: [PATCH 778/894] lavfi/drawutils: overhaul to improve pixel format support - No longer mixes u8 and u16 component accesses (this was UB) - De-duplicated 8->16 conversion - De-duplicated component -> plane+offset conversion - De-duplicated planar + packed RGB - No longer calls ff_fill_rgba_map - Removed redundant comp_mask data member - RGB0 and related formats no longer write an alpha value to the 0 byte - Non-planar YA formats now work correctly - High-bit-depth semi-planar YUV now works correctly --- libavfilter/drawutils.c | 110 +++++++++++++----------------- libavfilter/drawutils.h | 1 - tests/ref/fate/filter-pixfmts-pad | 20 +++--- 3 files changed, 58 insertions(+), 73 deletions(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 5308fcbc0f..cbb2582fe0 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -137,66 +137,49 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep)); draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w; draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h; - for (i = 0; i < (desc->nb_components - !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(flags & FF_DRAW_PROCESS_ALPHA))); i++) - draw->comp_mask[desc->comp[i].plane] |= - 1 << desc->comp[i].offset; return 0; } void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]) { unsigned i; - uint8_t rgba_map[4]; + uint8_t tmp8[4]; + const AVPixFmtDescriptor *desc = draw->desc; if (rgba != color->rgba) memcpy(color->rgba, rgba, sizeof(color->rgba)); - if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && - ff_fill_rgba_map(rgba_map, draw->format) >= 0) { - if (draw->nb_planes == 1) { - for (i = 0; i < 4; i++) { - color->comp[0].u8[rgba_map[i]] = rgba[i]; - if (draw->desc->comp[rgba_map[i]].depth > 8) { - color->comp[0].u16[rgba_map[i]] = color->comp[0].u8[rgba_map[i]] << 8; - } - } - } else { - for (i = 0; i < 4; i++) { - color->comp[rgba_map[i]].u8[0] = rgba[i]; - if (draw->desc->comp[rgba_map[i]].depth > 8) - color->comp[rgba_map[i]].u16[0] = color->comp[rgba_map[i]].u8[0] << (draw->desc->comp[rgba_map[i]].depth - 8); - } - } + + memset(color->comp, 0, sizeof(color->comp)); + + if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) { + memcpy(tmp8, rgba, sizeof(tmp8)); } else if (draw->nb_planes >= 2) { /* assume YUV */ - const AVPixFmtDescriptor *desc = draw->desc; - color->comp[desc->comp[0].plane].u8[desc->comp[0].offset] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); - color->comp[desc->comp[1].plane].u8[desc->comp[1].offset] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0); - color->comp[desc->comp[2].plane].u8[desc->comp[2].offset] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0); - color->comp[3].u8[0] = rgba[3]; -#define EXPAND(compn) \ - if (desc->comp[compn].depth > 8) \ - color->comp[desc->comp[compn].plane].u16[desc->comp[compn].offset] = \ - color->comp[desc->comp[compn].plane].u8[desc->comp[compn].offset] << \ - (draw->desc->comp[compn].depth + draw->desc->comp[compn].shift - 8) - EXPAND(3); - EXPAND(2); - EXPAND(1); - EXPAND(0); + tmp8[0] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); + tmp8[1] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0); + tmp8[2] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0); + tmp8[3] = rgba[3]; } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A || draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE || draw->format == AV_PIX_FMT_GRAY9LE || draw->format == AV_PIX_FMT_GRAY10LE || draw->format == AV_PIX_FMT_GRAY12LE || draw->format == AV_PIX_FMT_GRAY14LE) { - const AVPixFmtDescriptor *desc = draw->desc; - color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); - EXPAND(0); - color->comp[1].u8[0] = rgba[3]; - EXPAND(1); + tmp8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); + tmp8[1] = rgba[3]; } else { av_log(NULL, AV_LOG_WARNING, "Color conversion not implemented for %s\n", draw->desc->name); memset(color, 128, sizeof(*color)); + return; + } + + for (i = 0; i < desc->nb_components; i++) { + if (desc->comp[i].depth > 8) + color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = tmp8[i] << + (draw->desc->comp[i].depth + draw->desc->comp[i].shift - 8); + else + color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = tmp8[i]; } } @@ -302,11 +285,6 @@ static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end) *w >>= sub; } -static int component_used(FFDrawContext *draw, int plane, int comp) -{ - return (draw->comp_mask[plane] >> comp) & 1; -} - /* If alpha is in the [ 0 ; 0x1010101 ] range, then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range, and >> 24 gives a correct rounding. */ @@ -366,6 +344,9 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y; uint8_t *p0, *p; + nb_comp = draw->desc->nb_components - + !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); + /* TODO optimize if alpha = 0xFF */ clip_interval(dst_w, &x0, &w, NULL); clip_interval(dst_h, &y0, &h, NULL); @@ -381,7 +362,6 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); nb_planes += !nb_planes; for (plane = 0; plane < nb_planes; plane++) { - nb_comp = draw->pixelstep[plane]; p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); w_sub = w; h_sub = h; @@ -391,17 +371,19 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); for (comp = 0; comp < nb_comp; comp++) { const int depth = draw->desc->comp[comp].depth; + const int offset = draw->desc->comp[comp].offset; + const int index = offset / ((depth + 7) / 8); - if (!component_used(draw, plane, comp)) + if (draw->desc->comp[comp].plane != plane) continue; - p = p0 + comp; + p = p0 + offset; if (top) { if (depth <= 8) { - blend_line(p, color->comp[plane].u8[comp], alpha >> 1, + blend_line(p, color->comp[plane].u8[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } else { - blend_line16(p, color->comp[plane].u16[comp], alpha >> 1, + blend_line16(p, color->comp[plane].u16[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } @@ -409,14 +391,14 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, } if (depth <= 8) { for (y = 0; y < h_sub; y++) { - blend_line(p, color->comp[plane].u8[comp], alpha, + blend_line(p, color->comp[plane].u8[index], alpha, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); p += dst_linesize[plane]; } } else { for (y = 0; y < h_sub; y++) { - blend_line16(p, color->comp[plane].u16[comp], alpha, + blend_line16(p, color->comp[plane].u16[index], alpha, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); p += dst_linesize[plane]; @@ -424,11 +406,11 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, } if (bottom) { if (depth <= 8) { - blend_line(p, color->comp[plane].u8[comp], alpha >> 1, + blend_line(p, color->comp[plane].u8[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } else { - blend_line16(p, color->comp[plane].u16[comp], alpha >> 1, + blend_line16(p, color->comp[plane].u16[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } @@ -544,6 +526,9 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, uint8_t *p0, *p; const uint8_t *m; + nb_comp = draw->desc->nb_components - + !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); + clip_interval(dst_w, &x0, &mask_w, &xm0); clip_interval(dst_h, &y0, &mask_h, &ym0); mask += ym0 * mask_linesize; @@ -559,7 +544,6 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); nb_planes += !nb_planes; for (plane = 0; plane < nb_planes; plane++) { - nb_comp = draw->pixelstep[plane]; p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); w_sub = mask_w; h_sub = mask_h; @@ -569,21 +553,23 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); for (comp = 0; comp < nb_comp; comp++) { const int depth = draw->desc->comp[comp].depth; + const int offset = draw->desc->comp[comp].offset; + const int index = offset / ((depth + 7) / 8); - if (!component_used(draw, plane, comp)) + if (draw->desc->comp[comp].plane != plane) continue; - p = p0 + comp; + p = p0 + offset; m = mask; if (top) { if (depth <= 8) { blend_line_hv(p, draw->pixelstep[plane], - color->comp[plane].u8[comp], alpha, + color->comp[plane].u8[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, top); } else { blend_line_hv16(p, draw->pixelstep[plane], - color->comp[plane].u16[comp], alpha, + color->comp[plane].u16[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, top); @@ -594,7 +580,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, if (depth <= 8) { for (y = 0; y < h_sub; y++) { blend_line_hv(p, draw->pixelstep[plane], - color->comp[plane].u8[comp], alpha, + color->comp[plane].u8[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, 1 << draw->vsub[plane]); @@ -604,7 +590,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, } else { for (y = 0; y < h_sub; y++) { blend_line_hv16(p, draw->pixelstep[plane], - color->comp[plane].u16[comp], alpha, + color->comp[plane].u16[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, 1 << draw->vsub[plane]); @@ -615,13 +601,13 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, if (bottom) { if (depth <= 8) { blend_line_hv(p, draw->pixelstep[plane], - color->comp[plane].u8[comp], alpha, + color->comp[plane].u8[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, bottom); } else { blend_line_hv16(p, draw->pixelstep[plane], - color->comp[plane].u16[comp], alpha, + color->comp[plane].u16[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, bottom); diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h index 2ca2475585..396688514e 100644 --- a/libavfilter/drawutils.h +++ b/libavfilter/drawutils.h @@ -37,7 +37,6 @@ typedef struct FFDrawContext { enum AVPixelFormat format; unsigned nb_planes; int pixelstep[MAX_PLANES]; /*< offset between pixels */ - uint8_t comp_mask[MAX_PLANES]; /*< bitmask of used non-alpha components */ uint8_t hsub[MAX_PLANES]; /*< horizontal subsampling */ uint8_t vsub[MAX_PLANES]; /*< vertical subsampling */ uint8_t hsub_max; diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 74981cd6c1..d8c348a0fe 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -1,8 +1,8 @@ -0bgr 7bc6f5a1c44cdd7506174dccf52c68d7 -0rgb ff12e0f1e576b47a4c962729d5c0b868 +0bgr 55d41bba3609383bf658169f90b30b42 +0rgb 8e076dd0f8a9f4652595dffe3544f0f0 abgr 52738042432893de555e6a3833172806 argb 2a10108ac524b422b8a2393c064b3eab -bgr0 32207a2de1b2ac7937e940a8459b97c0 +bgr0 025d4d5e5691801ba39bc9de70e39df0 bgr24 f8b65ad845905c7d0c93ca28dfbb826f bgra 929aac15e848038e367c250037575f9f gbrap 5f16cccab5a17cb766c882e865995167 @@ -25,16 +25,16 @@ nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 nv24 193b9eadcc06ad5081609f76249b3e47 nv42 1738ad3c31c6c16e17679f5b09ce4677 -p210le 10b53de63b086de93c076d1d40f9da42 -p216le 0bbf778e1b6101a3f650ce0454a357f2 -p410le fcab6381bde9cd84b813925ff29be4d2 -p416le 6db094f8d7d27d7299bf9496ad66e2e0 -rgb0 78d500c8361ab6423a4826a00268c908 +p210le abc02945a9b9585f0914716e4787cefb +p216le 1b43feb94b8a030c0c699aa0deff017b +p410le 1f0294141ae1657d6c10c6a0d46a879f +p416le 320e558b7ee8d598231ae0763ecca275 +rgb0 0984eb985dabbe757ed6beb53db84eff rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 xyz12le 85abf80b77a9236a76ba0b00fcbdea2d -ya16le 940fafa240b9916de5f73cb20a552f24 -ya8 5fc0f471207ddf7aa01b07027d56b672 +ya16le d85740ba2cac9fa9ea8aaea8a5864407 +ya8 495daaca2dcb4f7aeba7652768b41ced yuv410p cb871dcc1e84a7ef1d21f9237b88cf6e yuv411p aec2c1740de9a62db0d41f4dda9121b0 yuv420p 4398e408fc35436ce4b20468946f58b6 From da92865b270c1890a163d653393e682e3b431756 Mon Sep 17 00:00:00 2001 From: rcombs Date: Thu, 23 Dec 2021 21:02:30 -0600 Subject: [PATCH 779/894] lavfi/drawutils: re-enable P010 and P016 support These formats now work as expected. --- libavfilter/drawutils.c | 2 -- tests/ref/fate/filter-pixfmts-pad | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index cbb2582fe0..65ed61aa92 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -91,8 +91,6 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) return AVERROR(ENOSYS); if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) return AVERROR(ENOSYS); - if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P016LE) - return AVERROR(ENOSYS); if (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || format == AV_PIX_FMT_YUVJ444P || format == AV_PIX_FMT_YUVJ411P || format == AV_PIX_FMT_YUVJ440P) full_range = 1; diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index d8c348a0fe..519473032e 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -25,6 +25,8 @@ nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 nv24 193b9eadcc06ad5081609f76249b3e47 nv42 1738ad3c31c6c16e17679f5b09ce4677 +p010le c57224f2dc09601c66aa3365b3cd7254 +p016le c57224f2dc09601c66aa3365b3cd7254 p210le abc02945a9b9585f0914716e4787cefb p216le 1b43feb94b8a030c0c699aa0deff017b p410le 1f0294141ae1657d6c10c6a0d46a879f From db28bb8fb46b5ef0554ac73c6ca741ca55e91451 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 5 Jan 2022 03:06:27 +0100 Subject: [PATCH 780/894] lavfi/libplacebo: support dovi metadata application libplacebo supports automatic dolby vision application, but it requires us to switch to a new API. Also add some logic to strip the dolby vision metadata from the output frames in any case where we end up changing the colorimetry. The libplacebo dependency bump is justified because neither 184 nor 192 are part of any stable libplacebo release, so users have to build from git anyways for this filter to exist. Signed-off-by: Niklas Haas --- configure | 2 +- libavfilter/vf_libplacebo.c | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 64538b17e2..8392c26015 100755 --- a/configure +++ b/configure @@ -6588,7 +6588,7 @@ enabled libopus && { require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create } } -enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.184.0" libplacebo/vulkan.h pl_vulkan_create +enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.192.0" libplacebo/vulkan.h pl_vulkan_create enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection enabled librav1e && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 5b1e7b5285..1386aaeb3a 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -47,6 +47,7 @@ typedef struct LibplaceboContext { int force_divisible_by; int normalize_sar; int apply_filmgrain; + int apply_dovi; int colorspace; int color_range; int color_primaries; @@ -281,8 +282,16 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) LibplaceboContext *s = avctx->priv; struct pl_render_params params; struct pl_frame image, target; - ok = pl_map_avframe(s->gpu, &image, NULL, in); - ok &= pl_map_avframe(s->gpu, &target, NULL, out); + ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( + .frame = in, + .map_dovi = s->apply_dovi, + )); + + ok &= pl_map_avframe_ex(s->gpu, &target, pl_avframe_params( + .frame = out, + .map_dovi = false, + )); + if (!ok) { err = AVERROR_EXTERNAL; goto fail; @@ -381,7 +390,7 @@ fail: static int filter_frame(AVFilterLink *link, AVFrame *in) { - int err; + int err, changed; AVFilterContext *ctx = link->dst; LibplaceboContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -400,6 +409,14 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) out->width = outlink->w; out->height = outlink->h; + if (s->apply_dovi && av_frame_get_side_data(in, AV_FRAME_DATA_DOVI_METADATA)) { + /* Output of dovi reshaping is always BT.2020+PQ, so infer the correct + * output colorspace defaults */ + out->colorspace = AVCOL_SPC_BT2020_NCL; + out->color_primaries = AVCOL_PRI_BT2020; + out->color_trc = AVCOL_TRC_SMPTE2084; + } + if (s->colorspace >= 0) out->colorspace = s->colorspace; if (s->color_range >= 0) @@ -411,6 +428,17 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) RET(process_frames(ctx, out, in)); + int changed_csp = s->colorspace != out->colorspace || + s->color_range != out->color_range || + s->color_trc != out->color_trc || + s->color_primaries != out->color_primaries; + + if (s->apply_dovi || changed_csp) { + /* Strip side data if no longer relevant */ + av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_RPU_BUFFER); + av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_METADATA); + } + if (s->apply_filmgrain) av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); @@ -559,6 +587,7 @@ static const AVOption libplacebo_options[] = { { "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC }, { "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, { "apply_filmgrain", "Apply film grain metadata", OFFSET(apply_filmgrain), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "apply_dolbyvision", "Apply Dolby Vision metadata", OFFSET(apply_dovi), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, { "deband", "Enable debanding", OFFSET(deband), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "deband_iterations", "Deband iterations", OFFSET(deband_iterations), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 16, DYNAMIC }, From a4289497755386435783774a4f520eb7fc23cbc9 Mon Sep 17 00:00:00 2001 From: Soft Works Date: Thu, 25 Nov 2021 02:41:32 +0000 Subject: [PATCH 781/894] avutils/hwcontext: When deriving a hwdevice, search for existing device in both directions The test /libavutil/tests/hwdevice checks that when deriving a device from a source device and then deriving back to the type of the source device, the result is matching the original source device, i.e. the derivation mechanism doesn't create a new device in this case. Previously, this test was usually passed, but only due to two different kind of flaws: 1. The test covers only a single level of derivation (and back) It derives device Y from device X and then Y back to the type of X and checks whether the result matches X. What it doesn't check for, are longer chains of derivation like: CUDA1 > OpenCL2 > CUDA3 and then back to OpenCL4 In that case, the second derivation returns the first device (CUDA3 == CUDA1), but when deriving OpenCL4, hwcontext.c was creating a new OpenCL4 context instead of returning OpenCL2, because there was no link from CUDA1 to OpenCL2 (only backwards from OpenCL2 to CUDA1) If the test would check for two levels of derivation, it would have failed. This patch fixes those (yet untested) cases by introducing forward references (derived_device) in addition to the existing back references (source_device). 2. hwcontext_qsv didn't properly set the source_device In case of QSV, hwcontext_qsv creates a source context internally (vaapi, dxva2 or d3d11va) without calling av_hwdevice_ctx_create_derived and without setting source_device. This way, the hwcontext test ran successful, but what practically happened, was that - for example - deriving vaapi from qsv didn't return the original underlying vaapi device and a new one was created instead: Exactly what the test is intended to detect and prevent. It just couldn't do so, because the original device was hidden (= not set as the source_device of the QSV device). This patch properly makes these setting and fixes all derivation scenarios. (at a later stage, /libavutil/tests/hwdevice should be extended to check longer derivation chains as well) Reviewed-by: Lynne Reviewed-by: Anton Khirnov Tested-by: Wenbin Chen Signed-off-by: softworkz Signed-off-by: Haihao Xiang --- libavutil/hwcontext.c | 38 ++++++++++++++++++++++++++++++++++ libavutil/hwcontext.h | 1 + libavutil/hwcontext_internal.h | 6 ++++++ libavutil/hwcontext_qsv.c | 13 +++++++++--- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 31c7840dba..1a50635018 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -122,6 +122,7 @@ static const AVClass hwdevice_ctx_class = { static void hwdevice_ctx_free(void *opaque, uint8_t *data) { AVHWDeviceContext *ctx = (AVHWDeviceContext*)data; + int i; /* uninit might still want access the hw context and the user * free() callback might destroy it, so uninit has to be called first */ @@ -132,6 +133,8 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data) ctx->free(ctx); av_buffer_unref(&ctx->internal->source_device); + for (i = 0; i < AV_HWDEVICE_TYPE_NB; i++) + av_buffer_unref(&ctx->internal->derived_devices[i]); av_freep(&ctx->hwctx); av_freep(&ctx->internal->priv); @@ -643,6 +646,26 @@ fail: return ret; } +static AVBufferRef* find_derived_hwdevice_ctx(AVBufferRef *src_ref, enum AVHWDeviceType type) +{ + AVBufferRef *tmp_ref; + AVHWDeviceContext *src_ctx; + int i; + + src_ctx = (AVHWDeviceContext*)src_ref->data; + if (src_ctx->type == type) + return src_ref; + + for (i = 0; i < AV_HWDEVICE_TYPE_NB; i++) + if (src_ctx->internal->derived_devices[i]) { + tmp_ref = find_derived_hwdevice_ctx(src_ctx->internal->derived_devices[i], type); + if (tmp_ref) + return tmp_ref; + } + + return NULL; +} + int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, @@ -666,6 +689,16 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, tmp_ref = tmp_ctx->internal->source_device; } + tmp_ref = find_derived_hwdevice_ctx(src_ref, type); + if (tmp_ref) { + dst_ref = av_buffer_ref(tmp_ref); + if (!dst_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + goto done; + } + dst_ref = av_hwdevice_ctx_alloc(type); if (!dst_ref) { ret = AVERROR(ENOMEM); @@ -687,6 +720,11 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, ret = AVERROR(ENOMEM); goto fail; } + tmp_ctx->internal->derived_devices[type] = av_buffer_ref(dst_ref); + if (!tmp_ctx->internal->derived_devices[type]) { + ret = AVERROR(ENOMEM); + goto fail; + } ret = av_hwdevice_ctx_init(dst_ref); if (ret < 0) goto fail; diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 04d19d89c2..0979fa2715 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -37,6 +37,7 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_OPENCL, AV_HWDEVICE_TYPE_MEDIACODEC, AV_HWDEVICE_TYPE_VULKAN, + AV_HWDEVICE_TYPE_NB, ///< number of hw device types, not part of API/ABI. }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index e6266494ac..f6fb67c491 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -109,6 +109,12 @@ struct AVHWDeviceInternal { * context it was derived from. */ AVBufferRef *source_device; + + /** + * An array of reference to device contexts which + * were derived from this device. + */ + AVBufferRef *derived_devices[AV_HWDEVICE_TYPE_NB]; }; struct AVHWFramesInternal { diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 853fb7f60d..91457c9c9e 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -274,7 +274,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) av_buffer_unref(&s->child_frames_ref); } -static void qsv_pool_release_dummy(void *opaque, uint8_t *data) +static void qsv_release_dummy(void *opaque, uint8_t *data) { } @@ -287,7 +287,7 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size) if (s->nb_surfaces_used < hwctx->nb_surfaces) { s->nb_surfaces_used++; return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1), - sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0); + sizeof(*hwctx->surfaces), qsv_release_dummy, NULL, 0); } return NULL; @@ -1596,8 +1596,15 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, child_device = (AVHWDeviceContext*)priv->child_device_ctx->data; impl = choose_implementation(device, child_device_type); + ret = qsv_device_derive_from_child(ctx, impl, child_device, 0); + if (ret >= 0) { + ctx->internal->source_device = av_buffer_ref(priv->child_device_ctx); + child_device->internal->derived_devices[ctx->type] = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), qsv_release_dummy, ctx, 0); + if (!child_device->internal->derived_devices[ctx->type]) + return AVERROR(ENOMEM); + } - return qsv_device_derive_from_child(ctx, impl, child_device, 0); + return ret; } const HWContextType ff_hwcontext_type_qsv = { From 0d82613b7dcdbe9e51b77f06baa72d5715343b8f Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 13 Dec 2021 14:40:55 +0800 Subject: [PATCH 782/894] lavc/qsvenc: set base address for V plane The SDK checks Data.V when using system memory for VP9 encoding. This fixed the error below: $ ffmpeg -qsv_device /dev/dri/renderD129 -f lavfi -i yuvtestsrc -c:v vp9_qsv -f null - [vp9_qsv @ 0x55b8387cbe90] Error during encoding: NULL pointer (-2) Video encoding failed Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index db6d397068..602436da63 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1535,8 +1535,23 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, qf->surface.Data.PitchLow = qf->frame->linesize[0]; qf->surface.Data.Y = qf->frame->data[0]; qf->surface.Data.UV = qf->frame->data[1]; - } + /* The SDK checks Data.V when using system memory for VP9 encoding */ + switch (frame->format) { + case AV_PIX_FMT_NV12: + qf->surface.Data.V = qf->surface.Data.UV + 1; + break; + + case AV_PIX_FMT_P010: + qf->surface.Data.V = qf->surface.Data.UV + 2; + break; + + default: + /* should not reach here */ + av_assert0(0); + break; + } + } qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000}); *new_frame = qf; From 8d4c0c8823194c71bb825f2ccd28b912f3791e08 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Fri, 29 Jan 2021 08:54:32 +0800 Subject: [PATCH 783/894] lavc/qsvdec: needn't free the string for AV_OPT_TYPE_STRING AVOption The string for AV_OPT_TYPE_STRING AVOption gets freed by av_opt_free() when closing the AVCodecContext Signed-off-by: Haihao Xiang --- libavcodec/qsvdec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 8bce9f2cf0..08370c8a0b 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -754,8 +754,6 @@ static av_cold int qsv_decode_close(AVCodecContext *avctx) { QSVDecContext *s = avctx->priv_data; - av_freep(&s->qsv.load_plugins); - qsv_decode_close_qsvcontext(&s->qsv); qsv_clear_buffers(s); From 7c6f9b9d638a9ae6020c8a388d5a6f2a89620663 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Wed, 5 Jan 2022 11:52:07 +0800 Subject: [PATCH 784/894] Revert "avutils/hwcontext: When deriving a hwdevice, search for existing device in both directions" This reverts commit a4289497755386435783774a4f520eb7fc23cbc9. There were objections on ML (see https://ffmpeg.org/pipermail/ffmpeg-devel/2021-December/290530.html) Signed-off-by: Haihao Xiang --- libavutil/hwcontext.c | 38 ---------------------------------- libavutil/hwcontext.h | 1 - libavutil/hwcontext_internal.h | 6 ------ libavutil/hwcontext_qsv.c | 13 +++--------- 4 files changed, 3 insertions(+), 55 deletions(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 1a50635018..31c7840dba 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -122,7 +122,6 @@ static const AVClass hwdevice_ctx_class = { static void hwdevice_ctx_free(void *opaque, uint8_t *data) { AVHWDeviceContext *ctx = (AVHWDeviceContext*)data; - int i; /* uninit might still want access the hw context and the user * free() callback might destroy it, so uninit has to be called first */ @@ -133,8 +132,6 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data) ctx->free(ctx); av_buffer_unref(&ctx->internal->source_device); - for (i = 0; i < AV_HWDEVICE_TYPE_NB; i++) - av_buffer_unref(&ctx->internal->derived_devices[i]); av_freep(&ctx->hwctx); av_freep(&ctx->internal->priv); @@ -646,26 +643,6 @@ fail: return ret; } -static AVBufferRef* find_derived_hwdevice_ctx(AVBufferRef *src_ref, enum AVHWDeviceType type) -{ - AVBufferRef *tmp_ref; - AVHWDeviceContext *src_ctx; - int i; - - src_ctx = (AVHWDeviceContext*)src_ref->data; - if (src_ctx->type == type) - return src_ref; - - for (i = 0; i < AV_HWDEVICE_TYPE_NB; i++) - if (src_ctx->internal->derived_devices[i]) { - tmp_ref = find_derived_hwdevice_ctx(src_ctx->internal->derived_devices[i], type); - if (tmp_ref) - return tmp_ref; - } - - return NULL; -} - int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, @@ -689,16 +666,6 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, tmp_ref = tmp_ctx->internal->source_device; } - tmp_ref = find_derived_hwdevice_ctx(src_ref, type); - if (tmp_ref) { - dst_ref = av_buffer_ref(tmp_ref); - if (!dst_ref) { - ret = AVERROR(ENOMEM); - goto fail; - } - goto done; - } - dst_ref = av_hwdevice_ctx_alloc(type); if (!dst_ref) { ret = AVERROR(ENOMEM); @@ -720,11 +687,6 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, ret = AVERROR(ENOMEM); goto fail; } - tmp_ctx->internal->derived_devices[type] = av_buffer_ref(dst_ref); - if (!tmp_ctx->internal->derived_devices[type]) { - ret = AVERROR(ENOMEM); - goto fail; - } ret = av_hwdevice_ctx_init(dst_ref); if (ret < 0) goto fail; diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 0979fa2715..04d19d89c2 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -37,7 +37,6 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_OPENCL, AV_HWDEVICE_TYPE_MEDIACODEC, AV_HWDEVICE_TYPE_VULKAN, - AV_HWDEVICE_TYPE_NB, ///< number of hw device types, not part of API/ABI. }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index f6fb67c491..e6266494ac 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -109,12 +109,6 @@ struct AVHWDeviceInternal { * context it was derived from. */ AVBufferRef *source_device; - - /** - * An array of reference to device contexts which - * were derived from this device. - */ - AVBufferRef *derived_devices[AV_HWDEVICE_TYPE_NB]; }; struct AVHWFramesInternal { diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 91457c9c9e..853fb7f60d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -274,7 +274,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) av_buffer_unref(&s->child_frames_ref); } -static void qsv_release_dummy(void *opaque, uint8_t *data) +static void qsv_pool_release_dummy(void *opaque, uint8_t *data) { } @@ -287,7 +287,7 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size) if (s->nb_surfaces_used < hwctx->nb_surfaces) { s->nb_surfaces_used++; return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1), - sizeof(*hwctx->surfaces), qsv_release_dummy, NULL, 0); + sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0); } return NULL; @@ -1596,15 +1596,8 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, child_device = (AVHWDeviceContext*)priv->child_device_ctx->data; impl = choose_implementation(device, child_device_type); - ret = qsv_device_derive_from_child(ctx, impl, child_device, 0); - if (ret >= 0) { - ctx->internal->source_device = av_buffer_ref(priv->child_device_ctx); - child_device->internal->derived_devices[ctx->type] = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), qsv_release_dummy, ctx, 0); - if (!child_device->internal->derived_devices[ctx->type]) - return AVERROR(ENOMEM); - } - return ret; + return qsv_device_derive_from_child(ctx, impl, child_device, 0); } const HWContextType ff_hwcontext_type_qsv = { From 07fd34aca744d6ae64cd4756943ce508ee0f9973 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 5 Jan 2022 04:58:25 +0100 Subject: [PATCH 785/894] avcodec/Makefile: Add missing mpegaudiodata.o dependency to MPEGAUDIO mpegaudiodec_template.c uses stuff from mpegaudiodata directly, yet this dependency was only indirectly fulfilled via mpegaudio-headers before 33e6d57f01dd4742a2e25ac5fa072b487d9d02ce. Since this commit, the latter only needs (and therefore provides) mpegaudiotabs, leading to compilation failures. This commit adds this missing direct dependency directly. (Sorry for not having checked indirect dependencies.) Found-by: Zane van Iperen Reviewed-by: Zane van Iperen Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7dc4ccb85f..242b48ff7c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -118,7 +118,8 @@ OBJS-$(CONFIG_MDCT) += mdct_float.o mdct_fixed_32.o OBJS-$(CONFIG_ME_CMP) += me_cmp.o OBJS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.o mediacodec_surface.o mediacodec_wrapper.o mediacodec_sw_buffer.o OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o -OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o +OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o \ + mpegaudiodata.o OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ From c1b55cb70ce748c1193d3251575b639daf9e96f0 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 3 Jan 2022 22:11:27 -0800 Subject: [PATCH 786/894] avformat/imf: fix error CPL root element is absent Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/imf_cpl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index 7055b49ae8..28798d3e36 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -688,7 +688,7 @@ int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl) } cpl_element = xmlDocGetRootElement(doc); - if (xmlStrcmp(cpl_element->name, "CompositionPlaylist")) { + if (!cpl_element || xmlStrcmp(cpl_element->name, "CompositionPlaylist")) { av_log(NULL, AV_LOG_ERROR, "The root element of the CPL is not CompositionPlaylist\n"); ret = AVERROR_INVALIDDATA; goto cleanup; From 59f1a46048109b8ec9f953d0d9348f9f1ae2a8c2 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 3 Jan 2022 07:59:19 -0800 Subject: [PATCH 787/894] avformat/imf: fix bad free() when directory name of the input url is empty Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/imfdec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index 503c8a2659..023f3556f6 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -624,8 +624,11 @@ static int imf_read_header(AVFormatContext *s) tmp_str = av_strdup(s->url); if (!tmp_str) return AVERROR(ENOMEM); + c->base_url = av_strdup(av_dirname(tmp_str)); + av_freep(&tmp_str); + if (!c->base_url) + return AVERROR(ENOMEM); - c->base_url = av_dirname(tmp_str); if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) return ret; From 76ffe1c2f1432001f2cdde42d53c839247a43380 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Tue, 4 Jan 2022 18:42:06 -0800 Subject: [PATCH 788/894] avformat/imf: fix CPL parsing error handling Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/imf_cpl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index 28798d3e36..366a1be9e2 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -807,7 +807,9 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) av_log(NULL, AV_LOG_ERROR, "Cannot read IMF CPL\n"); if (ret == 0) ret = AVERROR_INVALIDDATA; - } else { + goto clean_up; + } + LIBXML_TEST_VERSION filesize = buf.len; @@ -817,6 +819,7 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) AV_LOG_ERROR, "XML parsing failed when reading the IMF CPL\n"); ret = AVERROR_INVALIDDATA; + goto clean_up; } if ((ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl))) { @@ -833,8 +836,8 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) } xmlFreeDoc(doc); - } +clean_up: av_bprint_finalize(&buf, NULL); return ret; From 74afc3c6506df4a0b5c85ea84bfd485f3b8c9ecd Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Tue, 4 Jan 2022 18:42:07 -0800 Subject: [PATCH 789/894] avformat/imf: Fix indentation Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/imf_cpl.c | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index 366a1be9e2..f2ad9c05d6 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -810,32 +810,32 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) goto clean_up; } - LIBXML_TEST_VERSION + LIBXML_TEST_VERSION - filesize = buf.len; - doc = xmlReadMemory(buf.str, filesize, NULL, NULL, 0); - if (!doc) { - av_log(NULL, - AV_LOG_ERROR, - "XML parsing failed when reading the IMF CPL\n"); - ret = AVERROR_INVALIDDATA; - goto clean_up; - } + filesize = buf.len; + doc = xmlReadMemory(buf.str, filesize, NULL, NULL, 0); + if (!doc) { + av_log(NULL, + AV_LOG_ERROR, + "XML parsing failed when reading the IMF CPL\n"); + ret = AVERROR_INVALIDDATA; + goto clean_up; + } - if ((ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl))) { - av_log(NULL, AV_LOG_ERROR, "Cannot parse IMF CPL\n"); - } else { - av_log(NULL, - AV_LOG_INFO, - "IMF CPL ContentTitle: %s\n", - (*cpl)->content_title_utf8); - av_log(NULL, - AV_LOG_INFO, - "IMF CPL Id: " FF_IMF_UUID_FORMAT "\n", - UID_ARG((*cpl)->id_uuid)); - } + if ((ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl))) { + av_log(NULL, AV_LOG_ERROR, "Cannot parse IMF CPL\n"); + } else { + av_log(NULL, + AV_LOG_INFO, + "IMF CPL ContentTitle: %s\n", + (*cpl)->content_title_utf8); + av_log(NULL, + AV_LOG_INFO, + "IMF CPL Id: " FF_IMF_UUID_FORMAT "\n", + UID_ARG((*cpl)->id_uuid)); + } - xmlFreeDoc(doc); + xmlFreeDoc(doc); clean_up: av_bprint_finalize(&buf, NULL); From 21e25d2fe231ba6b9cb9809771ceb5a3f4f90410 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Wed, 5 Jan 2022 10:31:38 +1000 Subject: [PATCH 790/894] Changelog: add IMF demuxer Suggested-By: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index edb4152d0f..8e11fe6d35 100644 --- a/Changelog +++ b/Changelog @@ -44,6 +44,7 @@ version : - yadif_videotoolbox filter - VideoToolbox ProRes encoder - anlmf audio filter +- IMF demuxer (experimental) version 4.4: From 746df0a19aab263bdba26d3ea9ca7e05e95b9db6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 5 Jan 2022 08:37:15 -0300 Subject: [PATCH 791/894] Changelog: replace by 5.0 Signed-off-by: James Almer --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 8e11fe6d35..f8fcdb244d 100644 --- a/Changelog +++ b/Changelog @@ -1,7 +1,7 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. -version : +version 5.0: - ADPCM IMA Westwood encoder - Westwood AUD muxer - ADPCM IMA Acorn Replay decoder From ce4d459db186a7d8ac842685cd6256c9ac1b7f25 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 5 Jan 2022 08:37:55 -0300 Subject: [PATCH 792/894] Changelog: Add new line after 5.0 Signed-off-by: James Almer --- Changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog b/Changelog index f8fcdb244d..3dde3326be 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,9 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version : + + version 5.0: - ADPCM IMA Westwood encoder - Westwood AUD muxer From c4ecc643bb219872325b61544ecba4c95ada8d51 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Wed, 5 Jan 2022 14:33:30 +0800 Subject: [PATCH 793/894] avutil/hwcontext_vulkan: fixed incorrect memory offset This commit fixed hwupload in Vulkan: ffmpeg -init_hw_device vulkan -i test.jpg -vf hwupload,hwdownload,format=yuv420p -y out.jpg Signed-off-by: Wu Jianhua --- libavutil/hwcontext_vulkan.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index e90edea111..60a6cf6a91 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1872,12 +1872,14 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, f->size[0] = cont_memory_requirements.size; - for (int i = 0; i < planes; i++) { - bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; - bind_info[i].image = f->img[i]; - bind_info[i].memory = f->mem[0]; - bind_info[i].memoryOffset = !i ? 0 : cont_mem_size_list[i - 1]; + for (int i = 0, offset = 0; i < planes; i++) { + bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + bind_info[i].image = f->img[i]; + bind_info[i].memory = f->mem[0]; + bind_info[i].memoryOffset = offset; + f->offset[i] = bind_info[i].memoryOffset; + offset += cont_mem_size_list[i]; } } From aa8bb05d29599fb5372a715d30c290c7b723c24b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 5 Jan 2022 09:08:31 +0100 Subject: [PATCH 794/894] avcodec/Makefile: Add missing HEVC decoder->h274.o dependency Forgotten in 3cc3f5de2afda5b8f880c0817e9d67c2dafbfe1e. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 242b48ff7c..995b2792e4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -398,7 +398,8 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o OBJS-$(CONFIG_HCOM_DECODER) += hcom.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ - hevcdsp.o hevc_filter.o hevc_data.o + hevcdsp.o hevc_filter.o hevc_data.o \ + h274.o OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o From 49250b582ad109e04efd029cdb96020ef54fc2ee Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Sat, 1 Jan 2022 03:17:09 +0800 Subject: [PATCH 795/894] avfilter/vf_blend: fix un-checked potential memory allocation failure Signed-off-by: Wu Jianhua --- libavfilter/vf_blend.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c index b6f3c4fed3..2d433e439f 100644 --- a/libavfilter/vf_blend.c +++ b/libavfilter/vf_blend.c @@ -279,7 +279,11 @@ static AVFrame *blend_frame(AVFilterContext *ctx, AVFrame *top_buf, dst_buf = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!dst_buf) return top_buf; - av_frame_copy_props(dst_buf, top_buf); + + if (av_frame_copy_props(dst_buf, top_buf) < 0) { + av_frame_free(&dst_buf); + return top_buf; + } for (plane = 0; plane < s->nb_planes; plane++) { int hsub = plane == 1 || plane == 2 ? s->hsub : 0; From 9a194252c78c74c4455f837fd152b61904f5dc85 Mon Sep 17 00:00:00 2001 From: Wu Jianhua Date: Sat, 1 Jan 2022 02:09:53 +0800 Subject: [PATCH 796/894] avfilter: add a blend_vulkan filter This commit adds a blend_vulkan filter and a normal blend mode, and reserves support for introducing the blend modes in the future. Use the commands below to test: (href: https://trac.ffmpeg.org/wiki/Blend) I. make an image for test ffmpeg -f lavfi -i color=s=256x256,geq=r='H-1-Y':g='H-1-Y':b='H-1-Y' -frames 1 \ -y -pix_fmt yuv420p test.jpg II. blend in sw ffmpeg -i test.jpg -vf "split[a][b];[b]transpose[b];[a][b]blend=all_mode=normal,\ pseudocolor=preset=turbo" -y normal_sw.jpg III. blend in vulkan ffmpeg -init_hw_device vulkan -i test.jpg -vf "split[a][b];[b]transpose[b];\ [a]hwupload[a];[b]hwupload[b];[a][b]blend_vulkan=all_mode=normal,hwdownload,\ format=yuv420p,pseudocolor=preset=turbo" -y normal_vulkan.jpg Signed-off-by: Wu Jianhua --- configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_blend_vulkan.c | 499 ++++++++++++++++++++++++++++++++++ 4 files changed, 502 insertions(+) create mode 100644 libavfilter/vf_blend_vulkan.c diff --git a/configure b/configure index 8392c26015..f113f8f4ec 100755 --- a/configure +++ b/configure @@ -3616,6 +3616,7 @@ avgblur_opencl_filter_deps="opencl" avgblur_vulkan_filter_deps="vulkan spirv_compiler" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" +blend_vulkan_filter_deps="vulkan spirv_compiler" bm3d_filter_deps="avcodec" bm3d_filter_select="dct" boxblur_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 01c0338bbb..1adbea75bd 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -192,6 +192,7 @@ OBJS-$(CONFIG_BITPLANENOISE_FILTER) += vf_bitplanenoise.o OBJS-$(CONFIG_BLACKDETECT_FILTER) += vf_blackdetect.o OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o OBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o framesync.o +OBJS-$(CONFIG_BLEND_VULKAN_FILTER) += vf_blend_vulkan.o framesync.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_BM3D_FILTER) += vf_bm3d.o framesync.o OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o boxblur.o OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index dac615d7df..4325a3e557 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -181,6 +181,7 @@ extern const AVFilter ff_vf_bitplanenoise; extern const AVFilter ff_vf_blackdetect; extern const AVFilter ff_vf_blackframe; extern const AVFilter ff_vf_blend; +extern const AVFilter ff_vf_blend_vulkan; extern const AVFilter ff_vf_bm3d; extern const AVFilter ff_vf_boxblur; extern const AVFilter ff_vf_boxblur_opencl; diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c new file mode 100644 index 0000000000..f3560332b5 --- /dev/null +++ b/libavfilter/vf_blend_vulkan.c @@ -0,0 +1,499 @@ +/* + * copyright (c) 2021 Wu Jianhua + * The blend modes are based on the blend.c. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/random_seed.h" +#include "libavutil/opt.h" +#include "vulkan_filter.h" +#include "internal.h" +#include "framesync.h" +#include "blend.h" + +#define CGS 32 + +#define IN_TOP 0 +#define IN_BOTTOM 1 + +typedef struct FilterParamsVulkan { + const char *blend; + const char *blend_func; + double opacity; + enum BlendMode mode; +} FilterParamsVulkan; + +typedef struct BlendVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl; + FFFrameSync fs; + + VkDescriptorImageInfo top_images[3]; + VkDescriptorImageInfo bottom_images[3]; + VkDescriptorImageInfo output_images[3]; + + FilterParamsVulkan params[4]; + double all_opacity; + enum BlendMode all_mode; + + int initialized; +} BlendVulkanContext; + +#define DEFINE_BLEND_MODE(MODE, EXPR) \ +static const char blend_##MODE[] = "blend_"#MODE; \ +static const char blend_##MODE##_func[] = { \ + C(0, vec4 blend_##MODE(vec4 top, vec4 bottom, float opacity) { ) \ + C(1, vec4 dst = EXPR; ) \ + C(1, return dst; ) \ + C(0, } ) \ +}; + +#define A top +#define B bottom + +DEFINE_BLEND_MODE(NORMAL, A * opacity + B * (1.0f - opacity)) + +static inline void init_blend_func(FilterParamsVulkan *param) +{ +#define CASE(MODE) case BLEND_##MODE: \ + param->blend = blend_##MODE;\ + param->blend_func = blend_##MODE##_func; \ + break; + + switch (param->mode) { + CASE(NORMAL) + default: param->blend = NULL; break; + } + +#undef CASE +} + +static int config_params(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + + for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) { + FilterParamsVulkan *param = &s->params[plane]; + + if (s->all_mode >= 0) + param->mode = s->all_mode; + if (s->all_opacity < 1) + param->opacity = s->all_opacity; + + init_blend_func(param); + if (!param->blend) { + av_log(avctx, AV_LOG_ERROR, + "Currently the blend mode specified is not supported yet.\n"); + return AVERROR(EINVAL); + } + } + + return 0; +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_params(ctx); +} + +static av_cold int init_filter(AVFilterContext *avctx) +{ + int err = 0; + FFVkSampler *sampler; + FFVkSPIRVShader *shd; + BlendVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!sampler) + return AVERROR_EXTERNAL; + + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); + if (!s->pl) + return AVERROR(ENOMEM); + + { + FFVulkanDescriptorSetBinding image_descs[] = { + { + .name = "top_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->top_images, + .sampler = sampler, + }, + { + .name = "bottom_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->bottom_images, + .sampler = sampler, + }, + { + .name = "output_images", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->output_images, + }, + }; + + shd = ff_vk_init_shader(s->pl, "blend_compute", image_descs[0].stages); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 }); + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + + for (int i = 0, j = 0; i < planes; i++) { + for (j = 0; j < i; j++) + if (s->params[i].blend_func == s->params[j].blend_func) + break; + /* note: the bracket is needed, for GLSLD is a macro with multiple statements. */ + if (j == i) { + GLSLD(s->params[i].blend_func); + } + } + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_images[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + GLSLF(2, const vec4 top = texture(top_images[%i], pos); ,i); + GLSLF(2, const vec4 bottom = texture(bottom_images[%i], pos); ,i); + GLSLF(2, const float opacity = %f; ,s->params[i].opacity); + GLSLF(2, vec4 dst = %s(top, bottom, opacity); ,s->params[i].blend); + GLSLC(0, ); + GLSLF(2, imageStore(output_images[%i], pos, dst); ,i); + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(vkctx, shd, "main")); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); + } + + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + + s->initialized = 1; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out_frame, AVFrame *top_frame, AVFrame *bottom_frame) +{ + int err = 0; + VkCommandBuffer cmd_buf; + BlendVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &s->vkctx.vkfn; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + AVVkFrame *out = (AVVkFrame *)out_frame->data[0]; + AVVkFrame *top = (AVVkFrame *)top_frame->data[0]; + AVVkFrame *bottom = (AVVkFrame *)bottom_frame->data[0]; + + AVHWFramesContext *top_fc = (AVHWFramesContext*)top_frame->hw_frames_ctx->data; + AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom_frame->hw_frames_ctx->data; + + const VkFormat *top_formats = av_vkfmt_from_pixfmt(top_fc->sw_format); + const VkFormat *bottom_formats = av_vkfmt_from_pixfmt(bottom_fc->sw_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); + + for (int i = 0; i < planes; i++) { + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->top_images[i].imageView, top->img[i], + top_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->bottom_images[i].imageView, bottom->img[i], + bottom_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + output_formats[i], + ff_comp_identity_map)); + + s->top_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->bottom_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + ff_vk_update_descriptor_set(vkctx, s->pl, 0); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = top->layout[i], + .newLayout = s->top_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = top->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = bottom->layout[i], + .newLayout = s->bottom_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = bottom->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, + .oldLayout = out->layout[i], + .newLayout = s->output_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = out->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + }; + + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers); + + top->layout[i] = barriers[0].newLayout; + top->access[i] = barriers[0].dstAccessMask; + + bottom->layout[i] = barriers[1].newLayout; + bottom->access[i] = barriers[1].dstAccessMask; + + out->layout[i] = barriers[2].newLayout; + out->access[i] = barriers[2].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS) / CGS, + FFALIGN(s->vkctx.output_height, CGS) / CGS, 1); + + ff_vk_add_exec_dep(vkctx, s->exec, top_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, bottom_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + err = ff_vk_submit_exec_queue(vkctx, s->exec); + if (err) + return err; + + ff_vk_qf_rotate(&s->qf); + + return 0; + +fail: + ff_vk_discard_exec_deps(s->exec); + return err; +} + +static int blend_frame(FFFrameSync *fs) +{ + int err; + AVFilterContext *avctx = fs->parent; + BlendVulkanContext *s = avctx->priv; + AVFilterLink *outlink = avctx->outputs[0]; + AVFrame *top, *bottom, *out; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + RET(ff_framesync_get_frame(fs, IN_TOP, &top, 0)); + RET(ff_framesync_get_frame(fs, IN_BOTTOM, &bottom, 0)); + + RET(av_frame_copy_props(out, top)); + + if (!s->initialized) { + AVHWFramesContext *top_fc = (AVHWFramesContext*)top->hw_frames_ctx->data; + AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom->hw_frames_ctx->data; + if (top_fc->sw_format != bottom_fc->sw_format) { + av_log(avctx, AV_LOG_ERROR, + "Currently the sw format of the bottom video need to match the top!\n"); + return AVERROR(EINVAL); + } + RET(init_filter(avctx)); + } + + RET(process_frames(avctx, out, top, bottom)); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&out); + return err; +} + +static av_cold int init(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + + s->fs.on_event = blend_frame; + + return ff_vk_filter_init(avctx); +} + +static av_cold void uninit(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + + ff_framesync_uninit(&s->fs); + + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int config_props_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + BlendVulkanContext *s = avctx->priv; + AVFilterLink *toplink = avctx->inputs[IN_TOP]; + AVFilterLink *bottomlink = avctx->inputs[IN_BOTTOM]; + + if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) { + av_log(avctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", + avctx->input_pads[IN_TOP].name, toplink->w, toplink->h, + avctx->input_pads[IN_BOTTOM].name, bottomlink->w, bottomlink->h); + return AVERROR(EINVAL); + } + + outlink->sample_aspect_ratio = toplink->sample_aspect_ratio; + outlink->frame_rate = toplink->frame_rate; + + RET(ff_vk_filter_config_output(outlink)); + + RET(ff_framesync_init_dualinput(&s->fs, avctx)); + + RET(ff_framesync_configure(&s->fs)); + outlink->time_base = s->fs.time_base; + + RET(config_params(avctx)); + +fail: + return err; +} + +static int activate(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + return ff_framesync_activate(&s->fs); +} + +#define OFFSET(x) offsetof(BlendVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption blend_vulkan_options[] = { + { "c0_mode", "set component #0 blend mode", OFFSET(params[0].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "c1_mode", "set component #1 blend mode", OFFSET(params[1].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "c2_mode", "set component #2 blend mode", OFFSET(params[2].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "c3_mode", "set component #3 blend mode", OFFSET(params[3].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "all_mode", "set blend mode for all components", OFFSET(all_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, BLEND_NB - 1, FLAGS, "mode" }, + { "normal", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_NORMAL }, 0, 0, FLAGS, "mode" }, + + { "c0_opacity", "set color component #0 opacity", OFFSET(params[0].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "c1_opacity", "set color component #1 opacity", OFFSET(params[1].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "c2_opacity", "set color component #2 opacity", OFFSET(params[2].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "c3_opacity", "set color component #3 opacity", OFFSET(params[3].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "all_opacity", "set opacity for all color components", OFFSET(all_opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(blend_vulkan); + +static const AVFilterPad blend_vulkan_inputs[] = { + { + .name = "top", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_input, + }, + { + .name = "bottom", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_input, + }, +}; + + +static const AVFilterPad blend_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &config_props_output, + } +}; + +const AVFilter ff_vf_blend_vulkan = { + .name = "blend_vulkan", + .description = NULL_IF_CONFIG_SMALL("Blend two video frames in Vulkan"), + .priv_size = sizeof(BlendVulkanContext), + .init = &init, + .uninit = &uninit, + .activate = &activate, + FILTER_INPUTS(blend_vulkan_inputs), + FILTER_OUTPUTS(blend_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &blend_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .process_command = &process_command, +}; From a2372f904cdd42ea99d9b1d4a394a9561417f83b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 5 Jan 2022 14:59:21 +0100 Subject: [PATCH 797/894] avcodec/Makefile: Only compile nvenc.o if needed This fixes compilation errors in case nvenc is enabled (e.g. autodected) with both nvenc-based encoders disabled because nvenc uses ff_alloc_a53_sei(), yet only the nvenc-based encoders require atsc_a53. (This error does not manifest itself in case of static linking (nothing pulls in nvenc.o), but it exists with shared builds.) Signed-off-by: Andreas Rheinhardt Signed-off-by: Timo Rothenpieler --- libavcodec/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 995b2792e4..8c0c19ca27 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -135,7 +135,6 @@ OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ motion_est.o ratecontrol.o \ mpegvideoencdsp.o OBJS-$(CONFIG_MSS34DSP) += mss34dsp.o -OBJS-$(CONFIG_NVENC) += nvenc.o OBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o OBJS-$(CONFIG_QPELDSP) += qpeldsp.o OBJS-$(CONFIG_QSV) += qsv.o @@ -383,7 +382,7 @@ OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_H264_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o -OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o +OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o nvenc.o OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o @@ -404,7 +403,7 @@ OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o -OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o +OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o nvenc.o OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ hevc_data.o From df4cb384fb68454e23f8cc2b369e344c1bd8be7d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 5 Jan 2022 19:41:56 +0100 Subject: [PATCH 798/894] avcodec/Makefile: Add missing entry for ADPCM_IMA_AMV_ENCODER Forgotten in 555f5c1fc5ae0c4e7b0431dc3166c3fcf3f4e979. Reviewed-by: Zane van Iperen Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8c0c19ca27..cfc70a3eaf 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -888,6 +888,7 @@ OBJS-$(CONFIG_ADPCM_G726LE_DECODER) += g726.o OBJS-$(CONFIG_ADPCM_G726LE_ENCODER) += g726.o OBJS-$(CONFIG_ADPCM_IMA_ACORN_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_AMV_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_ALP_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_ALP_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_APC_DECODER) += adpcm.o adpcm_data.o From e228d7b0db7d6cb02a73bee6d3bf4f6ecf92d0bf Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 5 Jan 2022 19:57:58 +0100 Subject: [PATCH 799/894] configure: Add missing libshine->mpegaudioheader dependency Signed-off-by: Andreas Rheinhardt --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index f113f8f4ec..1225faf15a 100755 --- a/configure +++ b/configure @@ -3355,7 +3355,7 @@ librav1e_encoder_deps="librav1e" librav1e_encoder_select="extract_extradata_bsf" librsvg_decoder_deps="librsvg" libshine_encoder_deps="libshine" -libshine_encoder_select="audio_frame_queue" +libshine_encoder_select="audio_frame_queue mpegaudioheader" libspeex_decoder_deps="libspeex" libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" From 2b541b8c1d8b214d39c5f86fe8dc3a2aebe08f6d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 3 Jan 2022 12:35:39 +0100 Subject: [PATCH 800/894] avcodec/golomb: Factor writing golomb codes out Most users only want to either read or write golomb codes, not both. By splitting these headers one avoids having unnecesssary (get|put)_hits.h inclusions. Signed-off-by: Andreas Rheinhardt --- libavcodec/ffv1enc.c | 2 +- libavcodec/flacenc.c | 2 +- libavcodec/golomb.h | 133 ------------------------------ libavcodec/hevc_ps_enc.c | 2 +- libavcodec/jpeglsenc.c | 2 +- libavcodec/put_golomb.h | 168 ++++++++++++++++++++++++++++++++++++++ libavcodec/sonic.c | 1 + libavcodec/tests/golomb.c | 1 + 8 files changed, 174 insertions(+), 137 deletions(-) create mode 100644 libavcodec/put_golomb.h diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 69b9065343..d29f62bf56 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -36,8 +36,8 @@ #include "encode.h" #include "internal.h" #include "put_bits.h" +#include "put_golomb.h" #include "rangecoder.h" -#include "golomb.h" #include "mathops.h" #include "ffv1.h" diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 595928927d..9f6f449323 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -30,7 +30,7 @@ #include "bswapdsp.h" #include "encode.h" #include "put_bits.h" -#include "golomb.h" +#include "put_golomb.h" #include "internal.h" #include "lpc.h" #include "flac.h" diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 4d531cf805..164c2583b6 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -33,14 +33,12 @@ #include #include "get_bits.h" -#include "put_bits.h" #define INVALID_VLC 0x80000000 extern const uint8_t ff_golomb_vlc_len[512]; extern const uint8_t ff_ue_golomb_vlc_code[512]; extern const int8_t ff_se_golomb_vlc_code[512]; -extern const uint8_t ff_ue_golomb_len[256]; extern const uint8_t ff_interleaved_golomb_vlc_len[256]; extern const uint8_t ff_interleaved_ue_golomb_vlc_code[256]; @@ -615,135 +613,4 @@ static inline int get_te(GetBitContext *s, int r, char *file, const char *func, #define get_te0_golomb(a, r) get_te(a, r, __FILE__, __func__, __LINE__) #endif /* TRACE */ - -/** - * write unsigned exp golomb code. 2^16 - 2 at most - */ -static inline void set_ue_golomb(PutBitContext *pb, int i) -{ - av_assert2(i >= 0); - av_assert2(i <= 0xFFFE); - - if (i < 256) - put_bits(pb, ff_ue_golomb_len[i], i + 1); - else { - int e = av_log2(i + 1); - put_bits(pb, 2 * e + 1, i + 1); - } -} - -/** - * write unsigned exp golomb code. 2^32-2 at most. - */ -static inline void set_ue_golomb_long(PutBitContext *pb, uint32_t i) -{ - av_assert2(i <= (UINT32_MAX - 1)); - - if (i < 256) - put_bits(pb, ff_ue_golomb_len[i], i + 1); - else { - int e = av_log2(i + 1); - put_bits64(pb, 2 * e + 1, i + 1); - } -} - -/** - * write truncated unsigned exp golomb code. - */ -static inline void set_te_golomb(PutBitContext *pb, int i, int range) -{ - av_assert2(range >= 1); - av_assert2(i <= range); - - if (range == 2) - put_bits(pb, 1, i ^ 1); - else - set_ue_golomb(pb, i); -} - -/** - * write signed exp golomb code. 16 bits at most. - */ -static inline void set_se_golomb(PutBitContext *pb, int i) -{ - i = 2 * i - 1; - if (i < 0) - i ^= -1; //FIXME check if gcc does the right thing - set_ue_golomb(pb, i); -} - -/** - * write unsigned golomb rice code (ffv1). - */ -static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit, - int esc_len) -{ - int e; - - av_assert2(i >= 0); - - e = i >> k; - if (e < limit) - put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k)); - else - put_bits(pb, limit + esc_len, i - limit + 1); -} - -/** - * write unsigned golomb rice code (jpegls). - */ -static inline void set_ur_golomb_jpegls(PutBitContext *pb, int i, int k, - int limit, int esc_len) -{ - int e; - - av_assert2(i >= 0); - - e = (i >> k) + 1; - if (e < limit) { - while (e > 31) { - put_bits(pb, 31, 0); - e -= 31; - } - put_bits(pb, e, 1); - if (k) - put_sbits(pb, k, i); - } else { - while (limit > 31) { - put_bits(pb, 31, 0); - limit -= 31; - } - put_bits(pb, limit, 1); - put_bits(pb, esc_len, i - 1); - } -} - -/** - * write signed golomb rice code (ffv1). - */ -static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit, - int esc_len) -{ - int v; - - v = -2 * i - 1; - v ^= (v >> 31); - - set_ur_golomb(pb, v, k, limit, esc_len); -} - -/** - * write signed golomb rice code (flac). - */ -static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k, - int limit, int esc_len) -{ - int v; - - v = -2 * i - 1; - v ^= (v >> 31); - - set_ur_golomb_jpegls(pb, v, k, limit, esc_len); -} - #endif /* AVCODEC_GOLOMB_H */ diff --git a/libavcodec/hevc_ps_enc.c b/libavcodec/hevc_ps_enc.c index 47f252dd2c..72641b2ffb 100644 --- a/libavcodec/hevc_ps_enc.c +++ b/libavcodec/hevc_ps_enc.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "golomb.h" +#include "put_golomb.h" #include "hevc_ps.h" #include "put_bits.h" diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index beae3bb77f..83b2350a15 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -32,7 +32,7 @@ #include "encode.h" #include "get_bits.h" #include "put_bits.h" -#include "golomb.h" +#include "put_golomb.h" #include "internal.h" #include "mathops.h" #include "mjpeg.h" diff --git a/libavcodec/put_golomb.h b/libavcodec/put_golomb.h new file mode 100644 index 0000000000..9ca911fc3c --- /dev/null +++ b/libavcodec/put_golomb.h @@ -0,0 +1,168 @@ +/* + * exp golomb vlc writing stuff + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2004 Alex Beregszaszi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @brief + * exp golomb vlc writing stuff + * @author Michael Niedermayer and Alex Beregszaszi + */ + +#ifndef AVCODEC_PUT_GOLOMB_H +#define AVCODEC_PUT_GOLOMB_H + +#include +#include "put_bits.h" + +extern const uint8_t ff_ue_golomb_len[256]; + +/** + * write unsigned exp golomb code. 2^16 - 2 at most + */ +static inline void set_ue_golomb(PutBitContext *pb, int i) +{ + av_assert2(i >= 0); + av_assert2(i <= 0xFFFE); + + if (i < 256) + put_bits(pb, ff_ue_golomb_len[i], i + 1); + else { + int e = av_log2(i + 1); + put_bits(pb, 2 * e + 1, i + 1); + } +} + +/** + * write unsigned exp golomb code. 2^32-2 at most. + */ +static inline void set_ue_golomb_long(PutBitContext *pb, uint32_t i) +{ + av_assert2(i <= (UINT32_MAX - 1)); + + if (i < 256) + put_bits(pb, ff_ue_golomb_len[i], i + 1); + else { + int e = av_log2(i + 1); + put_bits64(pb, 2 * e + 1, i + 1); + } +} + +/** + * write truncated unsigned exp golomb code. + */ +static inline void set_te_golomb(PutBitContext *pb, int i, int range) +{ + av_assert2(range >= 1); + av_assert2(i <= range); + + if (range == 2) + put_bits(pb, 1, i ^ 1); + else + set_ue_golomb(pb, i); +} + +/** + * write signed exp golomb code. 16 bits at most. + */ +static inline void set_se_golomb(PutBitContext *pb, int i) +{ + i = 2 * i - 1; + if (i < 0) + i ^= -1; //FIXME check if gcc does the right thing + set_ue_golomb(pb, i); +} + +/** + * write unsigned golomb rice code (ffv1). + */ +static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit, + int esc_len) +{ + int e; + + av_assert2(i >= 0); + + e = i >> k; + if (e < limit) + put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k)); + else + put_bits(pb, limit + esc_len, i - limit + 1); +} + +/** + * write unsigned golomb rice code (jpegls). + */ +static inline void set_ur_golomb_jpegls(PutBitContext *pb, int i, int k, + int limit, int esc_len) +{ + int e; + + av_assert2(i >= 0); + + e = (i >> k) + 1; + if (e < limit) { + while (e > 31) { + put_bits(pb, 31, 0); + e -= 31; + } + put_bits(pb, e, 1); + if (k) + put_sbits(pb, k, i); + } else { + while (limit > 31) { + put_bits(pb, 31, 0); + limit -= 31; + } + put_bits(pb, limit, 1); + put_bits(pb, esc_len, i - 1); + } +} + +/** + * write signed golomb rice code (ffv1). + */ +static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit, + int esc_len) +{ + int v; + + v = -2 * i - 1; + v ^= (v >> 31); + + set_ur_golomb(pb, v, k, limit, esc_len); +} + +/** + * write signed golomb rice code (flac). + */ +static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k, + int limit, int esc_len) +{ + int v; + + v = -2 * i - 1; + v ^= (v >> 31); + + set_ur_golomb_jpegls(pb, v, k, limit, esc_len); +} + +#endif /* AVCODEC_PUT_GOLOMB_H */ diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c index 63a613f77d..cf1cfb1460 100644 --- a/libavcodec/sonic.c +++ b/libavcodec/sonic.c @@ -23,6 +23,7 @@ #include "get_bits.h" #include "golomb.h" #include "internal.h" +#include "put_golomb.h" #include "rangecoder.h" diff --git a/libavcodec/tests/golomb.c b/libavcodec/tests/golomb.c index 85b8a9390b..061cc013ce 100644 --- a/libavcodec/tests/golomb.c +++ b/libavcodec/tests/golomb.c @@ -27,6 +27,7 @@ #include "libavcodec/get_bits.h" #include "libavcodec/golomb.h" #include "libavcodec/put_bits.h" +#include "libavcodec/put_golomb.h" #define COUNT 8191 #define SIZE (COUNT * 4) From 3e17e0e5eff896f43654635bd3219da56f807f11 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 6 Jan 2022 20:07:07 -0300 Subject: [PATCH 801/894] avcodec/libdav1d: honor the requested strict_std_compliance level on supported builds Signed-off-by: James Almer --- libavcodec/libdav1d.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index bbc81a9dc9..8e45f533cb 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -236,6 +236,9 @@ static av_cold int libdav1d_init(AVCodecContext *c) s.all_layers = dav1d->all_layers; if (dav1d->operating_point >= 0) s.operating_point = dav1d->operating_point; +#if FF_DAV1D_VERSION_AT_LEAST(6,2) + s.strict_std_compliance = c->strict_std_compliance > 0; +#endif #if FF_DAV1D_VERSION_AT_LEAST(6,0) if (dav1d->frame_threads || dav1d->tile_threads) From 242ed971cb005157488b9a21942d9fb4be4d0347 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 3 Jan 2022 00:33:19 +0000 Subject: [PATCH 802/894] lavu/videotoolbox: add support for memory mapping frames Signed-off-by: Cameron Gutman Signed-off-by: Aman Karmani --- libavutil/hwcontext_videotoolbox.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index 0a8dbe9f33..026127d412 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -711,6 +711,30 @@ fail: return err; } +static int vt_map_from(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + int err; + + if (dst->format == AV_PIX_FMT_NONE) + dst->format = hwfc->sw_format; + else if (dst->format != hwfc->sw_format) + return AVERROR(ENOSYS); + + err = vt_map_frame(hwfc, dst, src, flags); + if (err) + return err; + + dst->width = src->width; + dst->height = src->height; + + err = av_frame_copy_props(dst, src); + if (err) + return err; + + return 0; +} + static int vt_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { @@ -736,6 +760,7 @@ const HWContextType ff_hwcontext_type_videotoolbox = { .transfer_get_formats = vt_transfer_get_formats, .transfer_data_to = vt_transfer_data_to, .transfer_data_from = vt_transfer_data_from, + .map_from = vt_map_from, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE }, }; From 7787cca18016c1f8100ab158f3479ba4b7e70467 Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Wed, 15 Dec 2021 16:06:37 +0800 Subject: [PATCH 803/894] lavc/av1dec: use frame split bsf Split packed data in case of its contains multiple show frame in some non-standard bitstream. This can benefit decoder which can decode continuously instead of interrupt with unexpected error. Signed-off-by: Fei Wang Signed-off-by: Haihao Xiang --- libavcodec/av1dec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index db110c50c7..09df2bf421 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -1240,6 +1240,7 @@ const AVCodec ff_av1_decoder = { .flush = av1_decode_flush, .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .priv_class = &av1_class, + .bsfs = "av1_frame_split", .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_AV1_DXVA2_HWACCEL HWACCEL_DXVA2(av1), From 035d2cc46368a7cdbf2585acdb1a83885706e43f Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Thu, 6 Jan 2022 11:00:40 +0800 Subject: [PATCH 804/894] doc/encoders.texi: Add doc for qsv Add doc for qsv decoder. Add more option's introduction to qsv encoder. Signed-off-by: Wenbin Chen Signed-off-by: Haihao Xiang --- doc/decoders.texi | 42 ++++++++ doc/encoders.texi | 253 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 292 insertions(+), 3 deletions(-) diff --git a/doc/decoders.texi b/doc/decoders.texi index 49ab735dce..de2429abba 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -126,6 +126,48 @@ Set amount of frame threads to use during decoding. The default value is 0 (auto @end table +@section QSV Decoders + +The family of Intel QuickSync Video decoders (VC1, MPEG-2, H.264, HEVC, +JPEG/MJPEG, VP8, VP9, AV1). + +@subsection Common Options + +The following options are supported by all qsv decoders. + +@table @option + +@item @var{async_depth} +Internal parallelization depth, the higher the value the higher the latency. + +@item @var{gpu_copy} +A GPU-accelerated copy between video and system memory +@table @samp +@item default +@item on +@item off +@end table + +@end table + +@subsection HEVC Options +Extra options for hevc_qsv. + +@table @option + +@item @var{load_plugin} +A user plugin to load in an internal session +@table @samp +@item none +@item hevc_sw +@item hevc_hw +@end table + +@item @var{load_plugins} +A :-separate list of hexadecimal plugin UIDs to load in an internal session + +@end table + @c man end VIDEO DECODERS @chapter Audio Decoders diff --git a/doc/encoders.texi b/doc/encoders.texi index e3b61de5a1..7cc8be1209 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3123,12 +3123,13 @@ Setting a higher @option{bits_per_mb} limit will improve the speed. For the fastest encoding speed set the @option{qscale} parameter (4 is the recommended value) and do not set a size constraint. -@section QSV encoders +@section QSV Encoders -The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG and VP9) +The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG +and VP9) +@subsection Ratecontrol Method The ratecontrol method is selected as follows: - @itemize @bullet @item When @option{global_quality} is specified, a quality-based mode is used. @@ -3176,6 +3177,7 @@ Note that depending on your system, a different mode than the one you specified may be selected by the encoder. Set the verbosity level to @var{verbose} or higher to see the actual settings used by the QSV runtime. +@subsection Global Options -> MSDK Options Additional libavcodec global options are mapped to MSDK options as follows: @itemize @@ -3212,6 +3214,251 @@ encoder use CAVLC instead of CABAC. @end itemize +@subsection Common Options +Following options are used by all qsv encoders. + +@table @option +@item @var{async_depth} +Specifies how many asynchronous operations an application performs +before the application explicitly synchronizes the result. If zero, +the value is not specified. + +@item @var{avbr_accuracy} +Accuracy of the AVBR ratecontrol (unit of tenth of percent). + +@item @var{avbr_convergence} +Convergence of the AVBR ratecontrol (unit of 100 frames) + +The parameters @var{avbr_accuracy} and @var{avbr_convergence} are for the +average variable bitrate control (AVBR) algorithm. +The algorithm focuses on overall encoding quality while meeting the specified +bitrate, @var{target_bitrate}, within the accuracy range @var{avbr_accuracy}, +after a @var{avbr_Convergence} period. This method does not follow HRD and the +instant bitrate is not capped or padded. + +@item @var{preset} +This option itemizes a range of choices from veryfast (best speed) to veryslow +(best quality). +@table @samp +@item veryfast +@item faster +@item fast +@item medium +@item slow +@item slower +@item veryslow +@end table + +@item @var{forced_idr} +Forcing I frames as IDR frames. + +@item @var{low_power} +For encoders set this flag to ON to reduce power consumption and GPU usage. +@end table + +@subsection H264 options +These options are used by h264_qsv + +@table @option +@item @var{extbrc} +Extended bitrate control. + +@item @var{recovery_point_sei} +Set this flag to insert the recovery point SEI message at the beginning of every +intra refresh cycle. + +@item @var{rdo} +Enable rate distortion optimization. + +@item @var{max_frame_size} +Maximum encoded frame size in bytes. + +@item @var{max_slice_size} +Maximum encoded slice size in bytes. + +@item @var{bitrate_limit} +Toggle bitrate limitations. +Modifies bitrate to be in the range imposed by the QSV encoder. Setting this +flag off may lead to violation of HRD conformance. Mind that specifying bitrate +below the QSV encoder range might significantly affect quality. If on this +option takes effect in non CQP modes: if bitrate is not in the range imposed +by the QSV encoder, it will be changed to be in the range. + +@item @var{mbbrc} +Setting this flag enables macroblock level bitrate control that generally +improves subjective visual quality. Enabling this flag may have negative impact +on performance and objective visual quality metric. + +@item @var{adaptive_i} +This flag controls insertion of I frames by the QSV encoder. Turn ON this flag +to allow changing of frame type from P and B to I. + +@item @var{adaptive_b} +This flag controls changing of frame type from B to P. + +@item @var{b_strategy} +This option controls usage of B frames as reference. + +@item @var{cavlc} +If set, CAVLC is used; if unset, CABAC is used for encoding. + +@item @var{vcm} +Video conferencing mode, please see ratecontrol method. + +@item @var{idr_interval} +Distance (in I-frames) between IDR frames. + +@item @var{pic_timing_sei} +Insert picture timing SEI with pic_struct_syntax element. + +@item @var{single_sei_nal_unit} +Put all the SEI messages into one NALU. + +@item @var{max_dec_frame_buffering} +Maximum number of frames buffered in the DPB. + +@item @var{look_ahead} +Use VBR algorithm with look ahead. + +@item @var{look_ahead_depth} +Depth of look ahead in number frames. + +@item @var{look_ahead_downsampling} +Downscaling factor for the frames saved for the lookahead analysis. +@table @samp +@item unknown +@item auto +@item off +@item 2x +@item 4x +@end table + +@item @var{int_ref_type} +Specifies intra refresh type. The major goal of intra refresh is improvement of +error resilience without significant impact on encoded bitstream size caused by +I frames. The SDK encoder achieves this by encoding part of each frame in +refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means +vertical refresh, by column of MBs. + +@item @var{int_ref_cycle_size} +Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are +invalid values. + +@item @var{int_ref_qp_delta} +Specifies QP difference for inserted intra MBs. This is signed value in +[-51, 51] range if target encoding bit-depth for luma samples is 8 and this +range is [-63, 63] for 10 bit-depth or [-75, 75] for 12 bit-depth respectively. + +@item @var{profile} +@table @samp +@item unknown +@item baseline +@item main +@item high +@end table + +@item @var{a53cc} +Use A53 Closed Captions (if available). + +@item @var{aud} +Insert the Access Unit Delimiter NAL. + +@item @var{mfmode} +Multi-Frame Mode. +@table @samp +@item off +@item auto +@end table + +@item @var{repeat_pps} +Repeat pps for every frame. +@end table + +@subsection HEVC Options +These options are used by hevc_qsv + +@table @option +@item @var{extbrc} +Extended bitrate control. + +@item @var{recovery_point_sei} +Set this flag to insert the recovery point SEI message at the beginning of every +intra refresh cycle. + +@item @var{rdo} +Enable rate distortion optimization. + +@item @var{idr_interval} +Distance (in I-frames) between IDR frames. +@table @samp +@item begin_only +Output an IDR-frame only at the beginning of the stream. +@end table + +@item @var{load_plugin} +A user plugin to load in an internal session. +@table @samp +@item none +@item hevc_sw +@item hevc_hw +@end table + +@item @var{load_plugins} +A :-separate list of hexadecimal plugin UIDs to load in +an internal session. + +@item @var{look_ahead_depth} +Depth of look ahead in number frames, available when extbrc option is enabled. + +@item @var{profile} +@table @samp +@item unknown +@item main +@item main10 +@item mainsp +@item rext +@end table + +@item @var{gpb} +1: GPB (generalized P/B frame) + +0: regular P frame. + +@item @var{tile_cols} +Number of columns for tiled encoding. + +@item @var{tile_rows} +Number of rows for tiled encoding. + +@item @var{aud} +Insert the Access Unit Delimiter NAL. +@end table + +@subsection MPEG2 Options +These options are used by mpeg2_qsv +@table @option +@item @var{profile} +@table @samp +@item unknown +@item simple +@item main +@item high +@end table +@end table + +@subsection VP9 Options +These options are used by vp9_qsv +@table @option +@item @var{profile} +@table @samp +@item unknown +@item profile0 +@item profile1 +@item profile2 +@item profile3 +@end table +@end table + @section snow @subsection Options From 72a822b975a2e98e856a7e7fd6b0deec326f4df4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 3 Jan 2022 13:06:40 +0100 Subject: [PATCH 805/894] avformat/takdec: Don't initialize get_bits context to read one value Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavcodec/tak.h | 1 - libavformat/takdec.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/tak.h b/libavcodec/tak.h index dc45a8c070..6069118971 100644 --- a/libavcodec/tak.h +++ b/libavcodec/tak.h @@ -44,7 +44,6 @@ #define TAK_LAST_FRAME_SIZE_BITS 24 #define TAK_ENCODER_CODEC_BITS 6 #define TAK_ENCODER_PROFILE_BITS 4 -#define TAK_ENCODER_VERSION_BITS 24 #define TAK_SAMPLE_RATE_MIN 6000 #define TAK_CHANNELS_MIN 1 #define TAK_BPS_MIN 8 diff --git a/libavformat/takdec.c b/libavformat/takdec.c index bb256e1190..cc1f049512 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -171,9 +171,8 @@ static int tak_read_header(AVFormatContext *s) get_bits(&gb, TAK_LAST_FRAME_SIZE_BITS); av_freep(&buffer); } else if (type == TAK_METADATA_ENCODER) { - init_get_bits8(&gb, buffer, size - 3); av_log(s, AV_LOG_VERBOSE, "encoder version: %0X\n", - get_bits_long(&gb, TAK_ENCODER_VERSION_BITS)); + AV_RL24(buffer)); av_freep(&buffer); } } From 6e163619e3e46e719903de3271e8c1b850b7d501 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 18:00:42 +0100 Subject: [PATCH 806/894] avformat/Makefile: Fix name of PhotoCD demuxer Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index c479ea998e..ba041bb22e 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -271,7 +271,7 @@ OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGM_PIPE_DEMUXER) += img2dec.o img2.o -OBJS-$(CONFIG_IMAGE_PHOTOCD_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PHOTOCD_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PPM_PIPE_DEMUXER) += img2dec.o img2.o From 41c62207f641b5cf3ae656068652f7dc958d5e79 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 17:01:09 +0100 Subject: [PATCH 807/894] configure: Add missing AMV muxer->riffenc dependency Reviewed-by: Zane van Iperen Signed-off-by: Andreas Rheinhardt --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 1225faf15a..6fe7b8513e 100755 --- a/configure +++ b/configure @@ -3393,6 +3393,7 @@ ac3_demuxer_select="ac3_parser" act_demuxer_select="riffdec" adts_muxer_select="mpeg4audio" aiff_muxer_select="iso_media" +amv_muxer_select="riffenc" asf_demuxer_select="riffdec" asf_o_demuxer_select="riffdec" asf_muxer_select="riffenc" From 217c90aac70af35e34381d7a99b4407686a3f47b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 19:42:05 +0100 Subject: [PATCH 808/894] avformat/matroskaenc: Fix build with only WebM muxer enabled In this case ff_isom_put_dvcc_dvvc() might not be available, leading to linking failures. Given that WebM currently doesn't support DOVI, this is fixed by #if'ing the offending code away if the Matroska muxer is not enabled. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 5cc59dc9f8..6ba1dadee9 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1123,6 +1123,7 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) { +#if CONFIG_MATROSKA_MUXER AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); @@ -1150,6 +1151,7 @@ static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) end_ebml_master(pb, mapping); } +#endif } static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, From 0c9c9bbd01bd82c35b6a908592d9dd6d9f4bd4a0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 3 Jan 2022 19:15:18 +0100 Subject: [PATCH 809/894] avcodec/apedec: Fix integer overflows in predictor_update_3930() Fixes: signed integer overflow: 1074134419 - -1075212485 cannot be represented in type 'int' Fixes: 43273/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APE_fuzzer-4706880883130368 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/apedec.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index b932263012..607304fe36 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -1088,13 +1088,13 @@ static av_always_inline int predictor_update_3930(APEPredictor *p, const int delayA) { int32_t predictionA, sign; - int32_t d0, d1, d2, d3; + uint32_t d0, d1, d2, d3; p->buf[delayA] = p->lastA[filter]; d0 = p->buf[delayA ]; - d1 = p->buf[delayA ] - p->buf[delayA - 1]; - d2 = p->buf[delayA - 1] - p->buf[delayA - 2]; - d3 = p->buf[delayA - 2] - p->buf[delayA - 3]; + d1 = p->buf[delayA ] - (unsigned)p->buf[delayA - 1]; + d2 = p->buf[delayA - 1] - (unsigned)p->buf[delayA - 2]; + d3 = p->buf[delayA - 2] - (unsigned)p->buf[delayA - 3]; predictionA = d0 * p->coeffsA[filter][0] + d1 * p->coeffsA[filter][1] + @@ -1105,10 +1105,10 @@ static av_always_inline int predictor_update_3930(APEPredictor *p, p->filterA[filter] = p->lastA[filter] + ((int)(p->filterA[filter] * 31U) >> 5); sign = APESIGN(decoded); - p->coeffsA[filter][0] += ((d0 < 0) * 2 - 1) * sign; - p->coeffsA[filter][1] += ((d1 < 0) * 2 - 1) * sign; - p->coeffsA[filter][2] += ((d2 < 0) * 2 - 1) * sign; - p->coeffsA[filter][3] += ((d3 < 0) * 2 - 1) * sign; + p->coeffsA[filter][0] += (((int32_t)d0 < 0) * 2 - 1) * sign; + p->coeffsA[filter][1] += (((int32_t)d1 < 0) * 2 - 1) * sign; + p->coeffsA[filter][2] += (((int32_t)d2 < 0) * 2 - 1) * sign; + p->coeffsA[filter][3] += (((int32_t)d3 < 0) * 2 - 1) * sign; return p->filterA[filter]; } From cafed377eb3fb56e113aa5169237215928a78cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 5 Jan 2022 10:22:06 +0200 Subject: [PATCH 810/894] Revert "lavc/aarch64: add hevc sao band 8x8 tiling" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f63f9be37c799ddc835af358034630d31fb7db02, as it breaks fate-hevc. Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 6 +----- libavcodec/aarch64/hevcdsp_sao_neon.S | 11 ++++------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 2002530266..b93cec9e44 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -77,11 +77,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; - c->sao_band_filter[0] = - c->sao_band_filter[1] = - c->sao_band_filter[2] = - c->sao_band_filter[3] = - c->sao_band_filter[4] = ff_hevc_sao_band_filter_8x8_8_neon; + c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; c->sao_edge_filter[0] = ff_hevc_sao_edge_filter_8x8_8_neon; c->sao_edge_filter[1] = c->sao_edge_filter[2] = diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index d524323fe8..73b0b3b056 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -3,7 +3,7 @@ * * AArch64 NEON optimised SAO functions for HEVC decoding * - * Copyright (c) 2020-2021 J. Dekker + * Copyright (c) 2020 Josh Dekker * * This file is part of FFmpeg. * @@ -35,7 +35,6 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 stp xzr, xzr, [sp, #32] stp xzr, xzr, [sp, #48] mov w8, #4 - sxtw x6, w6 0: ldrsh x9, [x4, x8, lsl #1] // sao_offset_val[k+1] subs w8, w8, #1 add w10, w8, w5 // k + sao_left_class @@ -44,9 +43,7 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 bne 0b ld1 {v16.16b-v19.16b}, [sp], #64 movi v20.8h, #1 - sub x2, x2, x6 // stride_dst - width - sub x3, x3, x6 // stride_src - width -1: mov x8, x6 // beginning of line +1: mov w8, w6 // beginning of line 2: // Simple layout for accessing 16bit values // with 8bit LUT. // @@ -55,7 +52,7 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 // |xDE#xAD|xCA#xFE|xBE#xEF|xFE#xED|.... // +-----------------------------------> // i-0 i-1 i-2 i-3 - ld1 {v2.8b}, [x1], #8 // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); + ld1 {v2.8b}, [x1] // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); uxtl v0.8h, v2.8b // load src[x] ushr v2.8h, v0.8h, #3 // >> BIT_DEPTH - 3 shl v1.8h, v2.8h, #1 // low (x2, accessing short) @@ -64,7 +61,7 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 tbx v2.16b, {v16.16b-v19.16b}, v1.16b // table add v1.8h, v0.8h, v2.8h // src[x] + table sqxtun v4.8b, v1.8h // clip + narrow - st1 {v4.8b}, [x0], #8 // store + st1 {v4.8b}, [x0] // store subs w8, w8, #8 // done 8 pixels bne 2b subs w7, w7, #1 // finished line, prep. new From df48b1d06f574138e78977598ddfe6788572811c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 5 Jan 2022 10:22:20 +0200 Subject: [PATCH 811/894] Revert "lavc/aarch64: add hevc sao edge 8x8" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c97ffc1a77ccaf901e642bd21ed26aaf75557745, as it breaks fate-hevc. Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 3 -- libavcodec/aarch64/hevcdsp_sao_neon.S | 51 ----------------------- 2 files changed, 54 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index b93cec9e44..747ff0412d 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -59,8 +59,6 @@ void ff_hevc_sao_band_filter_8x8_8_neon(uint8_t *_dst, uint8_t *_src, int width, int height); void ff_hevc_sao_edge_filter_16x16_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, int16_t *sao_offset_val, int eo, int width, int height); -void ff_hevc_sao_edge_filter_8x8_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, - int16_t *sao_offset_val, int eo, int width, int height); av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { @@ -78,7 +76,6 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; - c->sao_edge_filter[0] = ff_hevc_sao_edge_filter_8x8_8_neon; c->sao_edge_filter[1] = c->sao_edge_filter[2] = c->sao_edge_filter[3] = diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index 73b0b3b056..b8f0c65acc 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -135,54 +135,3 @@ function ff_hevc_sao_edge_filter_16x16_8_neon, export=1 // no lines to filter ret endfunc - -// ff_hevc_sao_edge_filter_8x8_8_neon(char *dst, char *src, ptrdiff stride_dst, -// int16 *sao_offset_val, int eo, int width, int height) -function ff_hevc_sao_edge_filter_8x8_8_neon, export=1 - adr x7, .Lsao_edge_pos - ldr w4, [x7, w4, uxtw #2] - ld1 {v3.8h}, [x3] - mov v3.h[7], v3.h[0] - mov v3.h[0], v3.h[1] - mov v3.h[1], v3.h[2] - mov v3.h[2], v3.h[7] - uzp2 v1.16b, v3.16b, v3.16b - uzp1 v0.16b, v3.16b, v3.16b - movi v2.16b, #2 - add x16, x0, x2 - lsl x2, x2, #1 - mov x15, #192 - mov x8, x1 - sub x9, x1, x4 - add x10, x1, x4 - mov x17, #4 -1: ld1 {v3.d}[0], [ x8], x15 - ld1 {v4.d}[0], [ x9], x15 - ld1 {v5.d}[0], [x10], x15 - ld1 {v3.d}[1], [ x8], x15 - ld1 {v4.d}[1], [ x9], x15 - ld1 {v5.d}[1], [x10], x15 - cmhi v16.16b, v4.16b, v3.16b - cmhi v17.16b, v3.16b, v4.16b - cmhi v18.16b, v5.16b, v3.16b - cmhi v19.16b, v3.16b, v5.16b - sub v20.16b, v16.16b, v17.16b - sub v21.16b, v18.16b, v19.16b - add v20.16b, v20.16b, v21.16b - add v20.16b, v20.16b, v2.16b - tbl v16.16b, {v0.16b}, v20.16b - tbl v17.16b, {v1.16b}, v20.16b - uxtl v20.8h, v3.8b - uxtl2 v21.8h, v3.16b - zip1 v18.16b, v16.16b, v17.16b - zip2 v19.16b, v16.16b, v17.16b - sqadd v20.8h, v18.8h, v20.8h - sqadd v21.8h, v19.8h, v21.8h - sqxtun v6.8b, v20.8h - sqxtun v7.8b, v21.8h - st1 {v6.8b}, [ x0], x2 - st1 {v7.8b}, [x16], x2 - subs x17, x17, #1 - b.ne 1b - ret -endfunc From 16fba44b4d0ab5e7414e1d9f9ee4a81d152da0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 5 Jan 2022 10:22:36 +0200 Subject: [PATCH 812/894] Revert "lavc/aarch64: add hevc sao edge 16x16" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a9214a2ca31c9d54f893c5ac4004a5ff30a08d10, as it breaks fate-hevc. Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 8 +-- libavcodec/aarch64/hevcdsp_sao_neon.S | 65 ----------------------- 2 files changed, 2 insertions(+), 71 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 747ff0412d..c785e46f79 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -57,8 +57,8 @@ void ff_hevc_sao_band_filter_8x8_8_neon(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int16_t *sao_offset_val, int sao_left_class, int width, int height); -void ff_hevc_sao_edge_filter_16x16_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, - int16_t *sao_offset_val, int eo, int width, int height); + + av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { @@ -76,10 +76,6 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; - c->sao_edge_filter[1] = - c->sao_edge_filter[2] = - c->sao_edge_filter[3] = - c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_16x16_8_neon; } if (bit_depth == 10) { c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index b8f0c65acc..d523bf584d 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -70,68 +70,3 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 bne 1b ret endfunc - -// ASSUMES STRIDE_SRC = 192 -.Lsao_edge_pos: -.word 1 // horizontal -.word 192 // vertical -.word 192 + 1 // 45 degree -.word 192 - 1 // 135 degree - -// ff_hevc_sao_edge_filter_16x16_8_neon(char *dst, char *src, ptrdiff stride_dst, -// int16 *sao_offset_val, int eo, int width, int height) -function ff_hevc_sao_edge_filter_16x16_8_neon, export=1 - adr x7, .Lsao_edge_pos - ld1 {v3.8h}, [x3] // load sao_offset_val - sxtw x5, w5 - ldr w4, [x7, w4, uxtw #2] // stride_src - mov v3.h[7], v3.h[0] // reorder to [1,2,0,3,4] - mov v3.h[0], v3.h[1] - mov v3.h[1], v3.h[2] - mov v3.h[2], v3.h[7] - // split 16bit values into two tables - uzp2 v1.16b, v3.16b, v3.16b // sao_offset_val -> upper - uzp1 v0.16b, v3.16b, v3.16b // sao_offset_val -> lower - movi v2.16b, #2 - mov x15, #192 - // strides between end of line and next src/dst - sub x15, x15, x5 // stride_src - width - sub x16, x2, x5 // stride_dst - width - mov x11, x1 // copy base src -1: // new line - mov x14, x5 // copy width - sub x12, x11, x4 // src_a (prev) = src - sao_edge_pos - add x13, x11, x4 // src_b (next) = src + sao_edge_pos -2: // process 16 bytes - ld1 {v3.16b}, [x11], #16 // load src - ld1 {v4.16b}, [x12], #16 // load src_a (prev) - ld1 {v5.16b}, [x13], #16 // load src_b (next) - cmhi v16.16b, v4.16b, v3.16b // (prev > cur) - cmhi v17.16b, v3.16b, v4.16b // (cur > prev) - cmhi v18.16b, v5.16b, v3.16b // (next > cur) - cmhi v19.16b, v3.16b, v5.16b // (cur > next) - sub v20.16b, v16.16b, v17.16b // diff0 = CMP(cur, prev) = (cur > prev) - (cur < prev) - sub v21.16b, v18.16b, v19.16b // diff1 = CMP(cur, next) = (cur > next) - (cur < next) - add v20.16b, v20.16b, v21.16b // diff = diff0 + diff1 - add v20.16b, v20.16b, v2.16b // offset_val = diff + 2 - tbl v16.16b, {v0.16b}, v20.16b - tbl v17.16b, {v1.16b}, v20.16b - uxtl v20.8h, v3.8b // src[0:7] - uxtl2 v21.8h, v3.16b // src[7:15] - zip1 v18.16b, v16.16b, v17.16b // sao_offset_val lower -> - zip2 v19.16b, v16.16b, v17.16b // sao_offset_val upper -> - sqadd v20.8h, v18.8h, v20.8h // + sao_offset_val - sqadd v21.8h, v19.8h, v21.8h - sqxtun v3.8b, v20.8h - sqxtun2 v3.16b, v21.8h - st1 {v3.16b}, [x0], #16 - subs x14, x14, #16 // filtered 16 bytes - b.ne 2b // do we have width to filter? - // no width to filter, setup next line - add x11, x11, x15 // stride src to next line - add x0, x0, x16 // stride dst to next line - subs w6, w6, #1 // filtered line - b.ne 1b // do we have lines to process? - // no lines to filter - ret -endfunc From 24b93022fee322c7a17e326e2d162a1fbc3698ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 5 Jan 2022 10:25:31 +0200 Subject: [PATCH 813/894] aarch64: Disable ff_hevc_sao_band_filter_8x8_8_neon out of precaution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While this function on its own passes all of fate-hevc, there's indications that the function might need to handle widths that aren't a multiple of 8 (noted in commit f63f9be37c799ddc835af358034630d31fb7db02, which later was reverted). Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index c785e46f79..1e40be740c 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -75,7 +75,11 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; - c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; + // This function is disabled, as it doesn't handle widths that aren't + // an even multiple of 8 correctly. fate-hevc doesn't exercise that + // for the current size, but if enabled for bigger sizes, the cases + // of non-multiple of 8 seem to arise. +// c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; } if (bit_depth == 10) { c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; From a8da11514347255f49e44d249075a1289ce250c9 Mon Sep 17 00:00:00 2001 From: John-Paul Stewart Date: Fri, 31 Dec 2021 20:11:47 -0500 Subject: [PATCH 814/894] avformat/mvdec: make audio stream conditional Only allocate an audio stream if there is one in the data. Silicon Graphics movie format will contain default values (16 bit samples, 2 audio channels, 22050 Hz sample rate) even when no audio is present in the file. This confuses FFmpeg into thinking such an audio stream is present with 0 samples in it. There is a flag value in the format to indicate whether or not audio is present. This patch checks that and behaves accordingly. Signed-off-by: John-Paul Stewart Reviewed-by: Andreas Rheinhardt Reviewed-by: Peter Ross --- libavformat/mvdec.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index ea955d2b11..0f0474141b 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -45,6 +45,10 @@ typedef struct MvContext { int aformat; ///< audio format } MvContext; +/* these magic numbers are defined in moviefile.h on Silicon Grahpics IRIX */ +#define MOVIE_SOUND 1 +#define MOVIE_SILENT 2 + #define AUDIO_FORMAT_SIGNED 401 static int mv_probe(const AVProbeData *p) @@ -305,18 +309,25 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 10); + fps = av_d2q(av_int2double(avio_rb64(pb)), INT_MAX); + /* allocate audio track first to prevent unnecessary seeking * (audio packet always precede video packet for a given frame) */ + v = avio_rb16(pb); + if (v == MOVIE_SOUND) { + /* movie has sound so allocate an audio stream */ ast = avformat_new_stream(avctx, NULL); if (!ast) return AVERROR(ENOMEM); + } else if (v != MOVIE_SILENT) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 2); vst = avformat_new_stream(avctx, NULL); if (!vst) return AVERROR(ENOMEM); - fps = av_d2q(av_int2double(avio_rb64(pb)), INT_MAX); avpriv_set_pts_info(vst, 64, fps.den, fps.num); - avio_skip(pb, 4); vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; vst->avg_frame_rate = fps; vst->duration = vst->nb_frames = avio_rb32(pb); @@ -338,6 +349,7 @@ static int mv_read_header(AVFormatContext *avctx) vst->codecpar->height = avio_rb32(pb); avio_skip(pb, 12); + if (ast) { ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->nb_frames = vst->nb_frames; ast->codecpar->sample_rate = avio_rb32(pb); @@ -373,6 +385,8 @@ static int mv_read_header(AVFormatContext *avctx) return AVERROR_INVALIDDATA; avio_skip(pb, 8); + } else + avio_skip(pb, 24); /* skip meaningless audio metadata */ var_read_metadata(avctx, "title", 0x80); var_read_metadata(avctx, "comment", 0x100); @@ -386,9 +400,11 @@ static int mv_read_header(AVFormatContext *avctx) if (avio_feof(pb)) return AVERROR_INVALIDDATA; avio_skip(pb, 8); + if (ast) { av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); - av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); timestamp += asize / (ast->codecpar->channels * (uint64_t)bytes_per_sample); + } + av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); From b24f0c82b3c05f1f9ed072a343b744635c828298 Mon Sep 17 00:00:00 2001 From: John-Paul Stewart Date: Fri, 31 Dec 2021 20:11:48 -0500 Subject: [PATCH 815/894] avformat/mvdec: re-indent after last commit Signed-off-by: John-Paul Stewart Reviewed-by: Andreas Rheinhardt Reviewed-by: Peter Ross --- libavformat/mvdec.c | 72 ++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 0f0474141b..4f233aff5f 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -316,9 +316,9 @@ static int mv_read_header(AVFormatContext *avctx) v = avio_rb16(pb); if (v == MOVIE_SOUND) { /* movie has sound so allocate an audio stream */ - ast = avformat_new_stream(avctx, NULL); - if (!ast) - return AVERROR(ENOMEM); + ast = avformat_new_stream(avctx, NULL); + if (!ast) + return AVERROR(ENOMEM); } else if (v != MOVIE_SILENT) return AVERROR_INVALIDDATA; @@ -350,41 +350,41 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 12); if (ast) { - ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - ast->nb_frames = vst->nb_frames; - ast->codecpar->sample_rate = avio_rb32(pb); - if (ast->codecpar->sample_rate <= 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid sample rate %d\n", ast->codecpar->sample_rate); - return AVERROR_INVALIDDATA; - } - avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - - bytes_per_sample = avio_rb32(pb); - - v = avio_rb32(pb); - if (v == AUDIO_FORMAT_SIGNED) { - switch (bytes_per_sample) { - case 1: - ast->codecpar->codec_id = AV_CODEC_ID_PCM_S8; - break; - case 2: - ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; - break; - default: - avpriv_request_sample(avctx, "Audio sample size %i bytes", bytes_per_sample); - break; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->nb_frames = vst->nb_frames; + ast->codecpar->sample_rate = avio_rb32(pb); + if (ast->codecpar->sample_rate <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid sample rate %d\n", ast->codecpar->sample_rate); + return AVERROR_INVALIDDATA; } - } else { - avpriv_request_sample(avctx, "Audio compression (format %i)", v); - } + avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - if (bytes_per_sample == 0) - return AVERROR_INVALIDDATA; + bytes_per_sample = avio_rb32(pb); - if (set_channels(avctx, ast, avio_rb32(pb)) < 0) - return AVERROR_INVALIDDATA; + v = avio_rb32(pb); + if (v == AUDIO_FORMAT_SIGNED) { + switch (bytes_per_sample) { + case 1: + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S8; + break; + case 2: + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; + break; + default: + avpriv_request_sample(avctx, "Audio sample size %i bytes", bytes_per_sample); + break; + } + } else { + avpriv_request_sample(avctx, "Audio compression (format %i)", v); + } - avio_skip(pb, 8); + if (bytes_per_sample == 0) + return AVERROR_INVALIDDATA; + + if (set_channels(avctx, ast, avio_rb32(pb)) < 0) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 8); } else avio_skip(pb, 24); /* skip meaningless audio metadata */ @@ -401,8 +401,8 @@ static int mv_read_header(AVFormatContext *avctx) return AVERROR_INVALIDDATA; avio_skip(pb, 8); if (ast) { - av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codecpar->channels * (uint64_t)bytes_per_sample); + av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); + timestamp += asize / (ast->codecpar->channels * (uint64_t)bytes_per_sample); } av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); } From 5bdd8e67e65db3fd623b1f6835eb8942f3a469bf Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 10:13:46 +0100 Subject: [PATCH 816/894] avformat/Makefile: Add missing libamqp->urldecode dependency Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index ba041bb22e..c81ceb2555 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -667,7 +667,7 @@ OBJS-$(CONFIG_UDPLITE_PROTOCOL) += udp.o ip.o OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o # external library protocols -OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o +OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o urldecode.o OBJS-$(CONFIG_LIBRIST_PROTOCOL) += librist.o OBJS-$(CONFIG_LIBRTMP_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPE_PROTOCOL) += librtmp.o From 78a840e7a3b6c4b8d4f665208d4ef4506ef9f5b5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 11:23:00 +0100 Subject: [PATCH 817/894] avformat/Makefile, amr: Add missing amr-demuxers->rawdec.o dependency Forgotten in 1f447fd95463bbf39a78d886359a3006d82f6a94. Also only enable amr_probe() and amr_read_header() in case the AMR demuxer is enabled; this avoids having to add a rawdec.o dependency to the muxer. Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 6 +++--- libavformat/amr.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index c81ceb2555..358245a587 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -88,10 +88,10 @@ OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o aiff.o id3v2enc.o OBJS-$(CONFIG_AIX_DEMUXER) += aixdec.o OBJS-$(CONFIG_ALP_DEMUXER) += alp.o OBJS-$(CONFIG_ALP_MUXER) += alp.o -OBJS-$(CONFIG_AMR_DEMUXER) += amr.o +OBJS-$(CONFIG_AMR_DEMUXER) += amr.o rawdec.o OBJS-$(CONFIG_AMR_MUXER) += amr.o rawenc.o -OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o -OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o +OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o rawdec.o +OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o rawdec.o OBJS-$(CONFIG_AMV_MUXER) += amvenc.o OBJS-$(CONFIG_ANM_DEMUXER) += anm.o OBJS-$(CONFIG_APC_DEMUXER) += apc.o diff --git a/libavformat/amr.c b/libavformat/amr.c index 0a044d69af..9250089cb1 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -66,6 +66,7 @@ static int amr_write_header(AVFormatContext *s) } #endif /* CONFIG_AMR_MUXER */ +#if CONFIG_AMR_DEMUXER static int amr_probe(const AVProbeData *p) { // Only check for "#!AMR" which could be amr-wb, amr-nb. @@ -140,7 +141,6 @@ static int amr_read_header(AVFormatContext *s) return 0; } -#if CONFIG_AMR_DEMUXER const AVInputFormat ff_amr_demuxer = { .name = "amr", .long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"), From a5a99cc11c7aea587c871d6ca3fc80d9f9828e27 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 11:33:31 +0100 Subject: [PATCH 818/894] avformat/amr: Don't reset AVFormatContext.priv_data The AMR muxer doesn't have a private context, so it's priv_data will be NULL. If it weren't, simply setting it to NULL would lead to a memleak. Signed-off-by: Andreas Rheinhardt --- libavformat/amr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index 9250089cb1..8e14052200 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -53,8 +53,6 @@ static int amr_write_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVCodecParameters *par = s->streams[0]->codecpar; - s->priv_data = NULL; - if (par->codec_id == AV_CODEC_ID_AMR_NB) { avio_write(pb, AMR_header, sizeof(AMR_header) - 1); /* magic number */ } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { From a22a71eb2c633335a037983fda0badc1863fc529 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 11:45:29 +0100 Subject: [PATCH 819/894] avformat/amr: Fix writing AMR header Regression since f282c34c009e3653ec160c3880e64fc1a9300d0e. Signed-off-by: Andreas Rheinhardt --- libavformat/amr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index 8e14052200..40d5bc9cc5 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -54,9 +54,9 @@ static int amr_write_header(AVFormatContext *s) AVCodecParameters *par = s->streams[0]->codecpar; if (par->codec_id == AV_CODEC_ID_AMR_NB) { - avio_write(pb, AMR_header, sizeof(AMR_header) - 1); /* magic number */ + avio_write(pb, AMR_header, sizeof(AMR_header)); /* magic number */ } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { - avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */ + avio_write(pb, AMRWB_header, sizeof(AMRWB_header)); /* magic number */ } else { return -1; } From b0a895a368a202e8e5f5c12ede0dcdb9c46af321 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 12:49:49 +0100 Subject: [PATCH 820/894] fate/amr[nw]b: Add remux tests Signed-off-by: Andreas Rheinhardt --- tests/fate/amrnb.mak | 8 +++++- tests/fate/amrwb.mak | 8 +++++- tests/ref/fate/amrnb-remux | 58 ++++++++++++++++++++++++++++++++++++++ tests/ref/fate/amrwb-remux | 58 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 tests/ref/fate/amrnb-remux create mode 100644 tests/ref/fate/amrwb-remux diff --git a/tests/fate/amrnb.mak b/tests/fate/amrnb.mak index c0feec25dc..f4f74f14d9 100644 --- a/tests/fate/amrnb.mak +++ b/tests/fate/amrnb.mak @@ -30,7 +30,13 @@ FATE_AMRNB += fate-amrnb-12k2 fate-amrnb-12k2: CMD = pcm -i $(TARGET_SAMPLES)/amrnb/12.2k.amr fate-amrnb-12k2: REF = $(SAMPLES)/amrnb/12.2k.pcm +FATE_AMRNB_REMUX-$(call ALLYES, FILE_PROTOCOL AMR_DEMUXER AMR_PARSER \ + AMR_MUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-amrnb-remux +fate-amrnb-remux: CMD = transcode amr $(TARGET_SAMPLES)/amrnb/10.2k.amr amr "-c copy" "-c copy -t 1" + $(FATE_AMRNB): CMP = stddev FATE_SAMPLES_AVCONV-$(call DEMDEC, AMR, AMRNB) += $(FATE_AMRNB) -fate-amrnb: $(FATE_AMRNB) +FATE_SAMPLES_FFMPEG += $(FATE_AMRNB_REMUX-yes) +fate-amrnb: $(FATE_AMRNB) $(FATE_AMRNB_REMUX-yes) diff --git a/tests/fate/amrwb.mak b/tests/fate/amrwb.mak index b93835d76d..617cefca00 100644 --- a/tests/fate/amrwb.mak +++ b/tests/fate/amrwb.mak @@ -41,7 +41,13 @@ FATE_AMRWB += fate-amrwb-23k85-2 fate-amrwb-23k85-2: CMD = pcm -i $(TARGET_SAMPLES)/amrwb/deus-23k85.awb fate-amrwb-23k85-2: REF = $(SAMPLES)/amrwb/deus-23k85.pcm +FATE_AMRWB_REMUX-$(call ALLYES, FILE_PROTOCOL MOV_DEMUXER AMR_PARSER AMR_MUXER \ + AMR_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-amrwb-remux +fate-amrwb-remux: CMD = transcode mov $(TARGET_SAMPLES)/amrwb/seed-23k85.awb amr "-c copy" "-c copy -t 1" + $(FATE_AMRWB): CMP = stddev FATE_SAMPLES_AVCONV-$(call DEMDEC, AMR, AMRWB) += $(FATE_AMRWB) -fate-amrwb: $(FATE_AMRWB) +FATE_SAMPLES_FFMPEG += $(FATE_AMRWB_REMUX-yes) +fate-amrwb: $(FATE_AMRWB) $(FATE_AMRWB_REMUX-yes) diff --git a/tests/ref/fate/amrnb-remux b/tests/ref/fate/amrnb-remux new file mode 100644 index 0000000000..4a78c479f2 --- /dev/null +++ b/tests/ref/fate/amrnb-remux @@ -0,0 +1,58 @@ +55311d26f9bb6faa36d99ee7cd34ee05 *tests/data/fate/amrnb-remux.amr +7674 tests/data/fate/amrnb-remux.amr +#tb 0: 1/8000 +#media_type 0: audio +#codec_id 0: amr_nb +#sample_rate 0: 8000 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 160, 27, 0xc9970c51 +0, 160, 160, 160, 27, 0xbaa00d05 +0, 320, 320, 160, 27, 0xa8af0d60 +0, 480, 480, 160, 27, 0xb6750d9f +0, 640, 640, 160, 27, 0xcd7d0e5f +0, 800, 800, 160, 27, 0xaf740d0f +0, 960, 960, 160, 27, 0xcb1c0f93 +0, 1120, 1120, 160, 27, 0xccfd0e02 +0, 1280, 1280, 160, 27, 0xb3e60d1e +0, 1440, 1440, 160, 27, 0xbe510d70 +0, 1600, 1600, 160, 27, 0xbeb30d65 +0, 1760, 1760, 160, 27, 0xd4730f2b +0, 1920, 1920, 160, 27, 0xa8540cd0 +0, 2080, 2080, 160, 27, 0xafdb0c14 +0, 2240, 2240, 160, 27, 0xd9930f24 +0, 2400, 2400, 160, 27, 0xbe5f0cec +0, 2560, 2560, 160, 27, 0xb44b0c6d +0, 2720, 2720, 160, 27, 0xdc160ec9 +0, 2880, 2880, 160, 27, 0xb8a20ce3 +0, 3040, 3040, 160, 27, 0xb9120c90 +0, 3200, 3200, 160, 27, 0xcdc70e7f +0, 3360, 3360, 160, 27, 0xc7c20f06 +0, 3520, 3520, 160, 27, 0xda530f0e +0, 3680, 3680, 160, 27, 0x90750abc +0, 3840, 3840, 160, 27, 0xa4840b6d +0, 4000, 4000, 160, 27, 0x96ed0ad1 +0, 4160, 4160, 160, 27, 0xb6b30c26 +0, 4320, 4320, 160, 27, 0x786909ce +0, 4480, 4480, 160, 27, 0xa4ae0c7d +0, 4640, 4640, 160, 27, 0x9ff90ba2 +0, 4800, 4800, 160, 27, 0x914c0c22 +0, 4960, 4960, 160, 27, 0xa8df0c9c +0, 5120, 5120, 160, 27, 0xb67f0d8e +0, 5280, 5280, 160, 27, 0xb6810cca +0, 5440, 5440, 160, 27, 0xa6110c80 +0, 5600, 5600, 160, 27, 0xda0f0ecf +0, 5760, 5760, 160, 27, 0xd6270e0d +0, 5920, 5920, 160, 27, 0xd2150ffc +0, 6080, 6080, 160, 27, 0xbd010da4 +0, 6240, 6240, 160, 27, 0xb9eb0e46 +0, 6400, 6400, 160, 27, 0xc8a80eb6 +0, 6560, 6560, 160, 27, 0xcc6b0cec +0, 6720, 6720, 160, 27, 0xab190db0 +0, 6880, 6880, 160, 27, 0xb3f90ca7 +0, 7040, 7040, 160, 27, 0xa84a0cc9 +0, 7200, 7200, 160, 27, 0xcdca0e8d +0, 7360, 7360, 160, 27, 0xaf8b0d1c +0, 7520, 7520, 160, 27, 0xd9980e15 +0, 7680, 7680, 160, 27, 0xcf810f8e +0, 7840, 7840, 160, 27, 0xb7810bd0 diff --git a/tests/ref/fate/amrwb-remux b/tests/ref/fate/amrwb-remux new file mode 100644 index 0000000000..c350fc0b61 --- /dev/null +++ b/tests/ref/fate/amrwb-remux @@ -0,0 +1,58 @@ +3634e03f106db1da796059bde3258efc *tests/data/fate/amrwb-remux.amr +31241 tests/data/fate/amrwb-remux.amr +#tb 0: 1/16000 +#media_type 0: audio +#codec_id 0: amr_wb +#sample_rate 0: 16000 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 320, 61, 0xc8891fe9 +0, 320, 320, 320, 61, 0xc2562027 +0, 640, 640, 320, 61, 0xe46e207f +0, 960, 960, 320, 61, 0xa27a1c46 +0, 1280, 1280, 320, 61, 0xf1d42007 +0, 1600, 1600, 320, 61, 0x50d61af4 +0, 1920, 1920, 320, 61, 0xbacf1eef +0, 2240, 2240, 320, 61, 0xbd691d7b +0, 2560, 2560, 320, 61, 0xfd1323a2 +0, 2880, 2880, 320, 61, 0x7ca01f0e +0, 3200, 3200, 320, 61, 0x2f812276 +0, 3520, 3520, 320, 61, 0xaef41ca8 +0, 3840, 3840, 320, 61, 0x2560211f +0, 4160, 4160, 320, 61, 0xd6ad1fd4 +0, 4480, 4480, 320, 61, 0x87d81d18 +0, 4800, 4800, 320, 61, 0x11531a44 +0, 5120, 5120, 320, 61, 0x83011d4f +0, 5440, 5440, 320, 61, 0xca39211f +0, 5760, 5760, 320, 61, 0xa0031e8d +0, 6080, 6080, 320, 61, 0x0b8a1980 +0, 6400, 6400, 320, 61, 0xd2931e62 +0, 6720, 6720, 320, 61, 0x0f7820fd +0, 7040, 7040, 320, 61, 0xcc8c2149 +0, 7360, 7360, 320, 61, 0x29f82236 +0, 7680, 7680, 320, 61, 0xf7a71f9c +0, 8000, 8000, 320, 61, 0xa64f1cba +0, 8320, 8320, 320, 61, 0x685321c1 +0, 8640, 8640, 320, 61, 0x48002221 +0, 8960, 8960, 320, 61, 0xef0a1f53 +0, 9280, 9280, 320, 61, 0x31e321a0 +0, 9600, 9600, 320, 61, 0xb49f1ead +0, 9920, 9920, 320, 61, 0xe5bb1f9d +0, 10240, 10240, 320, 61, 0xc5971d19 +0, 10560, 10560, 320, 61, 0x33182328 +0, 10880, 10880, 320, 61, 0xb791204e +0, 11200, 11200, 320, 61, 0x5db81bd8 +0, 11520, 11520, 320, 61, 0x9f171da7 +0, 11840, 11840, 320, 61, 0xec4a1974 +0, 12160, 12160, 320, 61, 0x980620e1 +0, 12480, 12480, 320, 61, 0x74cf1d0c +0, 12800, 12800, 320, 61, 0xea761ef7 +0, 13120, 13120, 320, 61, 0xa1da1cc7 +0, 13440, 13440, 320, 61, 0x68741b28 +0, 13760, 13760, 320, 61, 0x87991cee +0, 14080, 14080, 320, 61, 0x955f1d0f +0, 14400, 14400, 320, 61, 0x8eea1e69 +0, 14720, 14720, 320, 61, 0xadb21ede +0, 15040, 15040, 320, 61, 0xace61e29 +0, 15360, 15360, 320, 61, 0x67441c17 +0, 15680, 15680, 320, 61, 0x7f1b1e7c From f0daafe8e625baf599d8e5559147f284761fd134 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 12:50:55 +0100 Subject: [PATCH 821/894] fate/amrwb: Fix container type All the AMRWB samples are in a mov container. Also use FATE_SAMPLES_FFMPEG instead of FATE_SAMPLES_AVCONV. Signed-off-by: Andreas Rheinhardt --- tests/fate/amrwb.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/amrwb.mak b/tests/fate/amrwb.mak index 617cefca00..8450c28bba 100644 --- a/tests/fate/amrwb.mak +++ b/tests/fate/amrwb.mak @@ -48,6 +48,6 @@ fate-amrwb-remux: CMD = transcode mov $(TARGET_SAMPLES)/amrwb/seed-23k85.awb amr $(FATE_AMRWB): CMP = stddev -FATE_SAMPLES_AVCONV-$(call DEMDEC, AMR, AMRWB) += $(FATE_AMRWB) +FATE_SAMPLES_FFMPEG-$(call DEMDEC, MOV, AMRWB) += $(FATE_AMRWB) FATE_SAMPLES_FFMPEG += $(FATE_AMRWB_REMUX-yes) fate-amrwb: $(FATE_AMRWB) $(FATE_AMRWB_REMUX-yes) From 1beeeaf23ddb1630a66ec762a2270e46b76000d0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 16:57:56 +0100 Subject: [PATCH 822/894] avformat/Makefile: Add missing alp-muxer->rawenc.o dependency Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 358245a587..5f38d133f0 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -87,7 +87,7 @@ OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o aiff.o pcm.o \ OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o aiff.o id3v2enc.o OBJS-$(CONFIG_AIX_DEMUXER) += aixdec.o OBJS-$(CONFIG_ALP_DEMUXER) += alp.o -OBJS-$(CONFIG_ALP_MUXER) += alp.o +OBJS-$(CONFIG_ALP_MUXER) += alp.o rawenc.o OBJS-$(CONFIG_AMR_DEMUXER) += amr.o rawdec.o OBJS-$(CONFIG_AMR_MUXER) += amr.o rawenc.o OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o rawdec.o From 99f3fb8ea1d0f67c7fd0fda2fce136b5c71fc65e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 18:13:09 +0100 Subject: [PATCH 823/894] avformat/Makefile: Add entries for CRI, GEM and PGX image pipe demuxers Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index 5f38d133f0..d82512cec0 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -259,9 +259,11 @@ OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2enc.o img2.o OBJS-$(CONFIG_IMAGE2_ALIAS_PIX_DEMUXER) += img2_alias_pix.o OBJS-$(CONFIG_IMAGE2_BRENDER_PIX_DEMUXER) += img2_brender_pix.o OBJS-$(CONFIG_IMAGE_BMP_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_CRI_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_DDS_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_DPX_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_GEM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_GIF_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER) += img2dec.o img2.o @@ -271,6 +273,7 @@ OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGM_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PGX_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PHOTOCD_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER) += img2dec.o img2.o From a0d7e41ad7cb69600c1947571e55f08e36aa2e6d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 18:37:12 +0100 Subject: [PATCH 824/894] avformat/img2dec: Don't include disabled demuxers Signed-off-by: Andreas Rheinhardt --- libavformat/img2dec.c | 73 +++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index a6084ceef0..4d5ac51b53 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -1130,7 +1130,8 @@ static int gem_probe(const AVProbeData *p) return ret; } -#define IMAGEAUTO_DEMUXER(imgname, codecid)\ +#define IMAGEAUTO_DEMUXER_0(imgname, codecid) +#define IMAGEAUTO_DEMUXER_1(imgname, codecid)\ const AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ .name = AV_STRINGIFY(imgname) "_pipe",\ .long_name = NULL_IF_CONFIG_SMALL("piped " AV_STRINGIFY(imgname) " sequence"),\ @@ -1143,33 +1144,43 @@ const AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ .raw_codec_id = codecid,\ }; -IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP) -IMAGEAUTO_DEMUXER(cri, AV_CODEC_ID_CRI) -IMAGEAUTO_DEMUXER(dds, AV_CODEC_ID_DDS) -IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX) -IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR) -IMAGEAUTO_DEMUXER(gem, AV_CODEC_ID_GEM) -IMAGEAUTO_DEMUXER(gif, AV_CODEC_ID_GIF) -IMAGEAUTO_DEMUXER(j2k, AV_CODEC_ID_JPEG2000) -IMAGEAUTO_DEMUXER(jpeg, AV_CODEC_ID_MJPEG) -IMAGEAUTO_DEMUXER(jpegls, AV_CODEC_ID_JPEGLS) -IMAGEAUTO_DEMUXER(pam, AV_CODEC_ID_PAM) -IMAGEAUTO_DEMUXER(pbm, AV_CODEC_ID_PBM) -IMAGEAUTO_DEMUXER(pcx, AV_CODEC_ID_PCX) -IMAGEAUTO_DEMUXER(pgm, AV_CODEC_ID_PGM) -IMAGEAUTO_DEMUXER(pgmyuv, AV_CODEC_ID_PGMYUV) -IMAGEAUTO_DEMUXER(pgx, AV_CODEC_ID_PGX) -IMAGEAUTO_DEMUXER(photocd, AV_CODEC_ID_PHOTOCD) -IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR) -IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG) -IMAGEAUTO_DEMUXER(ppm, AV_CODEC_ID_PPM) -IMAGEAUTO_DEMUXER(psd, AV_CODEC_ID_PSD) -IMAGEAUTO_DEMUXER(qdraw, AV_CODEC_ID_QDRAW) -IMAGEAUTO_DEMUXER(sgi, AV_CODEC_ID_SGI) -IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST) -IMAGEAUTO_DEMUXER(svg, AV_CODEC_ID_SVG) -IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF) -IMAGEAUTO_DEMUXER(webp, AV_CODEC_ID_WEBP) -IMAGEAUTO_DEMUXER(xbm, AV_CODEC_ID_XBM) -IMAGEAUTO_DEMUXER(xpm, AV_CODEC_ID_XPM) -IMAGEAUTO_DEMUXER(xwd, AV_CODEC_ID_XWD) +#define IMAGEAUTO_DEMUXER_2(imgname, codecid, enabled) \ + IMAGEAUTO_DEMUXER_ ## enabled(imgname, codecid) +#define IMAGEAUTO_DEMUXER_3(imgname, codecid, config) \ + IMAGEAUTO_DEMUXER_2(imgname, codecid, config) +#define IMAGEAUTO_DEMUXER_EXT(imgname, codecid, uppercase_name) \ + IMAGEAUTO_DEMUXER_3(imgname, AV_CODEC_ID_ ## codecid, \ + CONFIG_IMAGE_ ## uppercase_name ## _PIPE_DEMUXER) +#define IMAGEAUTO_DEMUXER(imgname, codecid) \ + IMAGEAUTO_DEMUXER_EXT(imgname, codecid, codecid) + +IMAGEAUTO_DEMUXER(bmp, BMP) +IMAGEAUTO_DEMUXER(cri, CRI) +IMAGEAUTO_DEMUXER(dds, DDS) +IMAGEAUTO_DEMUXER(dpx, DPX) +IMAGEAUTO_DEMUXER(exr, EXR) +IMAGEAUTO_DEMUXER(gem, GEM) +IMAGEAUTO_DEMUXER(gif, GIF) +IMAGEAUTO_DEMUXER_EXT(j2k, JPEG2000, J2K) +IMAGEAUTO_DEMUXER_EXT(jpeg, MJPEG, JPEG) +IMAGEAUTO_DEMUXER(jpegls, JPEGLS) +IMAGEAUTO_DEMUXER(pam, PAM) +IMAGEAUTO_DEMUXER(pbm, PBM) +IMAGEAUTO_DEMUXER(pcx, PCX) +IMAGEAUTO_DEMUXER(pgm, PGM) +IMAGEAUTO_DEMUXER(pgmyuv, PGMYUV) +IMAGEAUTO_DEMUXER(pgx, PGX) +IMAGEAUTO_DEMUXER(photocd, PHOTOCD) +IMAGEAUTO_DEMUXER(pictor, PICTOR) +IMAGEAUTO_DEMUXER(png, PNG) +IMAGEAUTO_DEMUXER(ppm, PPM) +IMAGEAUTO_DEMUXER(psd, PSD) +IMAGEAUTO_DEMUXER(qdraw, QDRAW) +IMAGEAUTO_DEMUXER(sgi, SGI) +IMAGEAUTO_DEMUXER(sunrast, SUNRAST) +IMAGEAUTO_DEMUXER(svg, SVG) +IMAGEAUTO_DEMUXER(tiff, TIFF) +IMAGEAUTO_DEMUXER(webp, WEBP) +IMAGEAUTO_DEMUXER(xbm, XBM) +IMAGEAUTO_DEMUXER(xpm, XPM) +IMAGEAUTO_DEMUXER(xwd, XWD) From aeb5d943c613f50611ca49f5ffbfa8b24820b61d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 19:21:58 +0100 Subject: [PATCH 825/894] avformat/rtsp: #if unused functions away, fix -O0 compilation parse_rtsp_message() is only called if the rtsp demuxer is enabled and so it is normally compiled away if said demuxer is disabled. Yet this does not happen when compiling with -O0 and this leads to a linking failure because parse_rtsp_message() calls functions that may not be available if the rtsp demuxer is disabled. Fix this by properly #if'ing the unused functions away. Signed-off-by: Andreas Rheinhardt --- libavformat/rtsp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 1e091c7380..70c18941ca 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -246,6 +246,7 @@ static void finalize_rtp_handler_init(AVFormatContext *s, RTSPStream *rtsp_st, } } +#if CONFIG_RTSP_DEMUXER static int init_satip_stream(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -274,6 +275,7 @@ static int init_satip_stream(AVFormatContext *s) } return 0; } +#endif /* parse the rtpmap description: /[/] */ static int sdp_parse_rtpmap(AVFormatContext *s, @@ -2006,6 +2008,7 @@ redirect: #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */ #if CONFIG_RTPDEC +#if CONFIG_RTSP_DEMUXER static int parse_rtsp_message(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -2028,6 +2031,7 @@ static int parse_rtsp_message(AVFormatContext *s) return 0; } +#endif static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, uint8_t *buf, int buf_size, int64_t wait_end) From 2d0b17e820b84cceb95c29557e168a6ef98d4ce1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 20:47:31 +0100 Subject: [PATCH 826/894] configure: Let decklink indev suggest libzvbi Fixes build errors if libzvbi is enabled while libzvbi_teletextdec is disabled. Reviewed-by: Marton Balint Signed-off-by: Andreas Rheinhardt --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 6fe7b8513e..dba070dc3b 100755 --- a/configure +++ b/configure @@ -3501,6 +3501,7 @@ caca_outdev_deps="libcaca" decklink_deps_any="libdl LoadLibrary" decklink_indev_deps="decklink threads" decklink_indev_extralibs="-lstdc++" +decklink_indev_suggest="libzvbi" decklink_outdev_deps="decklink threads" decklink_outdev_suggest="libklvanc" decklink_outdev_extralibs="-lstdc++" From ad0b4afec57381c74f57dd3f3c65c49cc406c9fd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jan 2022 20:59:32 +0100 Subject: [PATCH 827/894] avdevice/iec61883: #if unused code away, fix -O0 compilation iec61883_parse_queue_hdv() is only called when the mpegts-demuxer is available and can be optimized away when not. Yet this optimization is not a given and it fails with e.g. GCC 11 when using -O0 in which case one will get a compilation error because the call to the unavailable avpriv_mpegts_parse_packet() is not optimized away. Therefore #if the offending code away in this case. Signed-off-by: Andreas Rheinhardt --- libavdevice/iec61883.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index e7b71c757a..72e14abff2 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -220,6 +220,7 @@ static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt) static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) { +#if CONFIG_MPEGTS_DEMUXER DVPacket *packet; int size; @@ -235,7 +236,7 @@ static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) if (size > 0) return size; } - +#endif return -1; } From d266bf17988271d529fd2209681889a78b9f259c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 7 Jan 2022 07:49:22 +0100 Subject: [PATCH 828/894] avformat/matroskaenc: Move AAC extradata check to other audio checks Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 6ba1dadee9..303aa1ce50 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1173,13 +1173,6 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) return 0; - if (par->codec_id == AV_CODEC_ID_AAC) { - ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, - &sample_rate, &output_sample_rate); - if (ret < 0) - return ret; - } - track_master = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); put_ebml_uint(pb, MATROSKA_ID_TRACKNUMBER, track->track_num); put_ebml_uid (pb, MATROSKA_ID_TRACKUID, track->uid); @@ -1377,6 +1370,12 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } if (par->codec_id == AV_CODEC_ID_OPUS) put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); + else if (par->codec_id == AV_CODEC_ID_AAC) { + ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, + &sample_rate, &output_sample_rate); + if (ret < 0) + return ret; + } put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); From e852b1b0631c14c81d49230931fac4593e7467e1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 7 Jan 2022 10:57:44 +0100 Subject: [PATCH 829/894] fate/subtitles: Fix check for fate-binsub-mksenc test Signed-off-by: Andreas Rheinhardt --- tests/fate/subtitles.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index 0c89adb0d1..8375cf2898 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -16,7 +16,7 @@ fate-sub-ass-to-ass-transcode: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/1ede FATE_SUBTITLES_ASS-$(CONFIG_ASS_DEMUXER) += fate-sub-ssa-to-ass-remux fate-sub-ssa-to-ass-remux: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/a9-misc.ssa -c copy -FATE_SUBTITLES-$(call ALLYES, ASS_DEMUXER, MATROSKA_MUXER) += fate-binsub-mksenc +FATE_SUBTITLES-$(call ALLYES, ASS_DEMUXER MATROSKA_MUXER) += fate-binsub-mksenc fate-binsub-mksenc: CMD = md5pipe -i $(TARGET_SAMPLES)/sub/1ededcbd7b.ass -c copy -f matroska -flags +bitexact -fflags +bitexact FATE_SUBTITLES_ASS-$(call DEMDEC, JACOSUB, JACOSUB) += fate-sub-jacosub From 52c1e9e530a46ba62b974f121c9d28a86900a632 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 7 Jan 2022 11:36:19 +0100 Subject: [PATCH 830/894] avformat/matroskaenc: Disable MKV-only code if MKV muxer is disabled The Matroska muxer has quite a lot of dependencies and lots of them are unnecessary for WebM. By disabling the Matroska-only code at compile time one can get rid of them. Signed-off-by: Andreas Rheinhardt --- configure | 1 - libavformat/Makefile | 4 +- libavformat/matroskaenc.c | 97 ++++++++++++++++++++++++--------------- 3 files changed, 60 insertions(+), 42 deletions(-) diff --git a/configure b/configure index dba070dc3b..1413122d87 100755 --- a/configure +++ b/configure @@ -3479,7 +3479,6 @@ w64_muxer_select="wav_muxer" wav_demuxer_select="riffdec" wav_muxer_select="riffenc" webm_chunk_muxer_select="webm_muxer" -webm_muxer_select="mpeg4audio riffenc" webm_dash_manifest_demuxer_select="matroska_demuxer" wtv_demuxer_select="mpegts_demuxer riffdec" wtv_muxer_select="mpegts_muxer riffenc" diff --git a/libavformat/Makefile b/libavformat/Makefile index d82512cec0..3dc6a479cc 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -585,9 +585,7 @@ OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ - av1.o avc.o hevc.o isom_tags.o \ - flacenc_header.o avlanguage.o \ - wv.o vorbiscomment.o + av1.o avlanguage.o OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o OBJS-$(CONFIG_WEBM_CHUNK_MUXER) += webm_chunk.o OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 303aa1ce50..152312102a 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -21,6 +21,8 @@ #include +#include "config.h" + #include "av1.h" #include "avc.h" #include "hevc.h" @@ -59,6 +61,11 @@ * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */ #define MAX_SEEKHEAD_ENTRIES 7 +#define MODE_MATROSKAv2 0x01 +#define MODE_WEBM 0x02 + +#define IS_WEBM(mkv) (CONFIG_WEBM_MUXER && CONFIG_MATROSKA_MUXER ? \ + ((mkv)->mode == MODE_WEBM) : CONFIG_WEBM_MUXER) #define IS_SEEKABLE(pb, mkv) (((pb)->seekable & AVIO_SEEKABLE_NORMAL) && \ !(mkv)->is_live) @@ -118,9 +125,6 @@ typedef struct mkv_track { int64_t ts_offset; } mkv_track; -#define MODE_MATROSKAv2 0x01 -#define MODE_WEBM 0x02 - typedef struct MatroskaMuxContext { const AVClass *class; int mode; @@ -640,6 +644,7 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, return 0; } +#if CONFIG_MATROSKA_MUXER static int put_wv_codecpriv(AVIOContext *pb, const AVCodecParameters *par) { if (par->extradata && par->extradata_size == 2) @@ -717,6 +722,7 @@ static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv, } return 0; } +#endif static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, const AVCodecParameters *par, @@ -726,6 +732,14 @@ static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_THEORA: return put_xiph_codecpriv(s, dyn_cp, par); + case AV_CODEC_ID_AV1: + if (par->extradata_size) + return ff_isom_write_av1c(dyn_cp, par->extradata, + par->extradata_size); + else + put_ebml_void(pb, 4 + 3); + break; +#if CONFIG_MATROSKA_MUXER case AV_CODEC_ID_FLAC: return put_flac_codecpriv(s, dyn_cp, par); case AV_CODEC_ID_WAVPACK: @@ -736,13 +750,6 @@ static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, case AV_CODEC_ID_HEVC: return ff_isom_write_hvcc(dyn_cp, par->extradata, par->extradata_size, 0); - case AV_CODEC_ID_AV1: - if (par->extradata_size) - return ff_isom_write_av1c(dyn_cp, par->extradata, - par->extradata_size); - else - put_ebml_void(pb, 4 + 3); - break; case AV_CODEC_ID_ALAC: if (par->extradata_size < 36) { av_log(s, AV_LOG_ERROR, @@ -759,8 +766,9 @@ static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, else put_ebml_void(pb, MAX_PCE_SIZE + 2 + 4); break; +#endif default: - if (par->codec_id == AV_CODEC_ID_PRORES && + if (CONFIG_MATROSKA_MUXER && par->codec_id == AV_CODEC_ID_PRORES && ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == AV_CODEC_ID_PRORES) { avio_wl32(dyn_cp, par->codec_tag); } else if (par->extradata_size && par->codec_id != AV_CODEC_ID_TTA) @@ -774,8 +782,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int native_id, int qt_id) { + MatroskaMuxContext av_unused *const mkv = s->priv_data; AVIOContext *dyn_cp; - MatroskaMuxContext *mkv = s->priv_data; uint8_t *codecpriv; int ret, codecpriv_size; @@ -785,6 +793,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, if (native_id) { ret = mkv_write_native_codecprivate(s, pb, par, dyn_cp); +#if CONFIG_MATROSKA_MUXER } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) { if (qt_id) { if (!par->codec_tag) @@ -826,6 +835,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, par->codec_tag = tag; ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); +#endif } if (ret >= 0) { @@ -991,7 +1001,7 @@ static void mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, end_ebml_master(pb, projection); } -static void mkv_write_field_order(AVIOContext *pb, int mode, +static void mkv_write_field_order(AVIOContext *pb, int is_webm, enum AVFieldOrder field_order) { switch (field_order) { @@ -1007,7 +1017,7 @@ static void mkv_write_field_order(AVIOContext *pb, int mode, case AV_FIELD_BT: put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED); - if (mode != MODE_WEBM) { + if (!is_webm) { switch (field_order) { case AV_FIELD_TT: put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, @@ -1031,7 +1041,8 @@ static void mkv_write_field_order(AVIOContext *pb, int mode, } static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, - AVStream *st, int mode, int *h_width, int *h_height) + AVStream *st, int is_webm, + int *h_width, int *h_height) { const AVDictionaryEntry *tag; MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB; @@ -1106,7 +1117,7 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; // if webm, do not write unsupported modes - if ((mode == MODE_WEBM && + if ((is_webm && format > MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM && format != MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT) || format >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB) { @@ -1192,7 +1203,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, if (st->disposition & AV_DISPOSITION_FORCED) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1); - if (mkv->mode == MODE_WEBM) { + if (IS_WEBM(mkv)) { const char *codec_id; if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { for (j = 0; ff_webm_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { @@ -1271,7 +1282,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, && av_cmp_q(av_inv_q(st->r_frame_rate), st->time_base) > 0) put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->r_frame_rate.den / st->r_frame_rate.num); - if (!native_id && + if (CONFIG_MATROSKA_MUXER && !native_id && ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) && ((!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id) && par->codec_id != AV_CODEC_ID_RAWVIDEO) || par->codec_id == AV_CODEC_ID_SVQ1 || @@ -1293,11 +1304,11 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , par->width); put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height); - mkv_write_field_order(pb, mkv->mode, par->field_order); + mkv_write_field_order(pb, IS_WEBM(mkv), par->field_order); // check both side data and metadata for stereo information, // write the result to the bitstream if any is found - ret = mkv_write_stereo_mode(s, pb, st, mkv->mode, + ret = mkv_write_stereo_mode(s, pb, st, IS_WEBM(mkv), &display_width_div, &display_height_div); if (ret < 0) @@ -1318,7 +1329,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, return AVERROR(EINVAL); } if (d_width != par->width || display_width_div != 1 || display_height_div != 1) { - if (mkv->mode == MODE_WEBM || display_width_div != 1 || display_height_div != 1) { + if (IS_WEBM(mkv) || display_width_div != 1 || display_height_div != 1) { put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, par->height / display_height_div); } else { @@ -1335,7 +1346,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } else if (display_width_div != 1 || display_height_div != 1) { put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , par->width / display_width_div); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, par->height / display_height_div); - } else if (mkv->mode != MODE_WEBM) + } else if (!IS_WEBM(mkv)) put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN); if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { @@ -1347,9 +1358,8 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, end_ebml_master(pb, subinfo); - if (mkv->mode != MODE_WEBM) { + if (!IS_WEBM(mkv)) mkv_write_dovi(s, pb, st); - } break; @@ -1370,12 +1380,14 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } if (par->codec_id == AV_CODEC_ID_OPUS) put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); +#if CONFIG_MATROSKA_MUXER else if (par->codec_id == AV_CODEC_ID_AAC) { ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, &sample_rate, &output_sample_rate); if (ret < 0) return ret; } +#endif put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); @@ -1410,10 +1422,10 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id); return AVERROR(ENOSYS); } - if (mkv->mode != MODE_WEBM && st->disposition & AV_DISPOSITION_DESCRIPTIONS) + if (!IS_WEBM(mkv) && st->disposition & AV_DISPOSITION_DESCRIPTIONS) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1); - if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) + if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) native_id = MATROSKA_TRACK_TYPE_SUBTITLE; put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id); @@ -1423,7 +1435,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, return AVERROR(EINVAL); } - if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) { + if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) { track->codecpriv_offset = avio_tell(pb); ret = mkv_write_codecprivate(s, pb, par, native_id, qt_id); if (ret < 0) @@ -1642,7 +1654,7 @@ static int mkv_write_tags(AVFormatContext *s) } } - if (mkv->nb_attachments && mkv->mode != MODE_WEBM) { + if (mkv->nb_attachments && !IS_WEBM(mkv)) { for (i = 0; i < s->nb_streams; i++) { const mkv_track *track = &mkv->tracks[i]; const AVStream *st = s->streams[i]; @@ -1695,7 +1707,7 @@ static int mkv_write_chapters(AVFormatContext *s) return ret; editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0); - if (mkv->mode != MODE_WEBM) { + if (!IS_WEBM(mkv)) { put_ebml_uint(dyn_cp, MATROSKA_ID_EDITIONFLAGDEFAULT, 1); /* If mkv_write_tags() has already been called, then any tags * corresponding to chapters will be put into a new Tags element. */ @@ -1855,7 +1867,7 @@ static int mkv_write_header(AVFormatContext *s) int ret, i, version = 2; int64_t creation_time; - if (mkv->mode != MODE_WEBM || + if (!IS_WEBM(mkv) || av_dict_get(s->metadata, "stereo_mode", NULL, 0) || av_dict_get(s->metadata, "alpha_mode", NULL, 0)) version = 4; @@ -1900,7 +1912,7 @@ static int mkv_write_header(AVFormatContext *s) else put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT); - if (mkv->mode != MODE_WEBM) + if (!IS_WEBM(mkv)) put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, mkv->segment_uid, 16); } else { const char *ident = "Lavf"; @@ -1948,7 +1960,7 @@ static int mkv_write_header(AVFormatContext *s) if (ret < 0) return ret; - if (mkv->mode != MODE_WEBM) { + if (!IS_WEBM(mkv)) { ret = mkv_write_attachments(s); if (ret < 0) return ret; @@ -2010,6 +2022,7 @@ static int mkv_blockgroup_size(int pkt_size, int track_num_size) return size; } +#if CONFIG_MATROSKA_MUXER static int mkv_strip_wavpack(const uint8_t *src, uint8_t **pdst, int *size) { uint8_t *dst; @@ -2062,6 +2075,7 @@ fail: av_freep(&dst); return ret; } +#endif static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, uint32_t blockid, const AVPacket *pkt, int keyframe) @@ -2089,6 +2103,7 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, pkt->size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), mkv->cluster_pos, track_number, keyframe != 0); +#if CONFIG_MATROSKA_MUXER if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 && (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) { err = ff_avc_parse_nal_units_buf(pkt->data, &data, &size); @@ -2096,11 +2111,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) { /* extradata is Annex B, assume the bitstream is too and convert it */ err = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL); - } else if (par->codec_id == AV_CODEC_ID_AV1) { - err = ff_av1_filter_obus_buf(pkt->data, &data, &size, &offset); } else if (par->codec_id == AV_CODEC_ID_WAVPACK) { err = mkv_strip_wavpack(pkt->data, &data, &size); } else +#endif + if (par->codec_id == AV_CODEC_ID_AV1) { + err = ff_av1_filter_obus_buf(pkt->data, &data, &size, &offset); + } else data = pkt->data; if (err < 0) { @@ -2109,7 +2126,8 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, return err; } - if (par->codec_id == AV_CODEC_ID_PRORES && size >= 8) { + if (CONFIG_MATROSKA_MUXER && + par->codec_id == AV_CODEC_ID_PRORES && size >= 8) { /* Matroska specification requires to remove the first QuickTime atom */ size -= 8; @@ -2261,6 +2279,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) &side_data_size); switch (par->codec_id) { +#if CONFIG_MATROSKA_MUXER case AV_CODEC_ID_AAC: if (side_data_size && mkv->track.bc) { int filler, output_sample_rate = 0; @@ -2302,6 +2321,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) par->extradata = old_extradata; } break; +#endif // FIXME: Remove the following once libaom starts propagating extradata during init() // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2012 case AV_CODEC_ID_AV1: @@ -2721,7 +2741,8 @@ static int mkv_init(struct AVFormatContext *s) si->avoid_negative_ts_use_pts = 1; } - if (!strcmp(s->oformat->name, "webm")) { + if (!CONFIG_MATROSKA_MUXER || + (CONFIG_WEBM_MUXER && !strcmp(s->oformat->name, "webm"))) { mkv->mode = MODE_WEBM; mkv->write_crc = 0; } else @@ -2755,7 +2776,7 @@ static int mkv_init(struct AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 1000); if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) { - if (mkv->mode == MODE_WEBM) { + if (IS_WEBM(mkv)) { av_log(s, AV_LOG_WARNING, "Stream %d will be ignored " "as WebM doesn't support attachments.\n", i); } else if (!get_mimetype(st)) { @@ -2783,7 +2804,7 @@ static int mkv_check_bitstream(AVFormatContext *s, AVStream *st, { int ret = 1; - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + if (CONFIG_MATROSKA_MUXER && st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) { From ffb000fff8f945a5b30f1df8ab1cb2e8300cdabd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 3 Jan 2022 13:48:39 +0100 Subject: [PATCH 831/894] avcodec/jpeglsdec: Avoid get_bits_long() where possible It is possible here, because the values of ff_log2_run used here are actually in the range 0..15 given that run_index is in the range 0..31. Signed-off-by: Andreas Rheinhardt --- libavcodec/jpeglsdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 32c0d2eb3f..269c71dc18 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -277,7 +277,7 @@ static inline int ls_decode_line(JLSState *state, MJpegDecodeContext *s, /* decode aborted run */ r = ff_log2_run[state->run_index[comp]]; if (r) - r = get_bits_long(&s->gb, r); + r = get_bits(&s->gb, r); if (x + r * stride > w) { r = (w - x) / stride; } From 1850c610e72c690a42dbde467011e22d73e73a78 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Fri, 7 Jan 2022 22:03:21 +0530 Subject: [PATCH 832/894] avformat/hlsenc: convey stream id to segment streams --- libavformat/hlsenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 459129818a..ef8973cea1 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -900,6 +900,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) st->sample_aspect_ratio = vs->streams[i]->sample_aspect_ratio; st->time_base = vs->streams[i]->time_base; av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0); + st->id = vs->streams[i]->id; } vs->start_pos = 0; From 0ddae119ace370bfa0c2ba8a06886f253ff53263 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 8 Jan 2022 20:47:26 +0100 Subject: [PATCH 833/894] avformat/rawvideodec: Disable option accidentally added for v210(x) 41f213c3bf629d549400e935e7f123e6cfa959ab accidentally added an unused pixel_format option to the v210(x) demuxers. Remove it before it really becomes part of the API. Reviewed-by: Limin Wang Signed-off-by: Andreas Rheinhardt --- libavformat/rawvideodec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 68547fc50f..3f92211af1 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -126,8 +126,9 @@ static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt) #define OFFSET(x) offsetof(RawVideoDemuxerContext, x) #define DEC AV_OPT_FLAG_DECODING_PARAM static const AVOption rawvideo_options[] = { - { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, + /* pixel_format is not used by the v210 demuxers. */ { "pixel_format", "set pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = "yuv420p"}, 0, 0, DEC }, + { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC }, { NULL }, }; @@ -175,7 +176,7 @@ const AVInputFormat ff_bitpacked_demuxer = { static const AVClass v210_demuxer_class = { .class_name = "v210(x) demuxer", .item_name = av_default_item_name, - .option = rawvideo_options, + .option = rawvideo_options + 1, .version = LIBAVUTIL_VERSION_INT, }; From 750c765ca421ba4546461f803f9ce2396399fb67 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 1 Jan 2022 09:57:05 +0100 Subject: [PATCH 834/894] avcodec/mpeg12dec: Don't set write-only variable MpegEncContext.picture_number is write-only for MPEG-1/2 decoding. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12dec.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 35dfc74fe7..6ad9fb245c 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1066,7 +1066,6 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx) s2->chroma_format = 1; s->mpeg_enc_ctx_allocated = 0; - s->mpeg_enc_ctx.picture_number = 0; s->repeat_field = 0; avctx->color_range = AVCOL_RANGE_MPEG; return 0; @@ -1092,9 +1091,6 @@ static int mpeg_decode_update_thread_context(AVCodecContext *avctx, if (!ctx->mpeg_enc_ctx_allocated) memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext)); - if (!(s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)) - s->picture_number++; - return 0; } #endif @@ -2072,10 +2068,7 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) ff_print_debug_info(s, s->current_picture_ptr, pict); ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG2); } else { - if (avctx->active_thread_type & FF_THREAD_FRAME) - s->picture_number++; /* latency of 1 frame for I- and P-frames */ - /* XXX: use another variable than picture_number */ if (s->last_picture_ptr) { int ret = av_frame_ref(pict, s->last_picture_ptr->f); if (ret < 0) From 4fc4cf49315c96531a7675140502df222ae8e942 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 1 Jan 2022 12:12:22 +0100 Subject: [PATCH 835/894] avcodec/mpegvideo: Don't unnecessarily allocate buffers Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 1c2b28f450..af433153f2 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -371,17 +371,17 @@ static int init_duplicate_context(MpegEncContext *s) s->pblocks[i] = &s->block[i]; } - if (!(s->block32 = av_mallocz(sizeof(*s->block32))) || - !(s->dpcm_macroblock = av_mallocz(sizeof(*s->dpcm_macroblock)))) - return AVERROR(ENOMEM); - s->dpcm_direction = 0; - if (s->avctx->codec_tag == AV_RL32("VCR2")) { // exchange uv FFSWAP(void *, s->pblocks[4], s->pblocks[5]); } if (s->out_format == FMT_H263) { + if (!(s->block32 = av_mallocz(sizeof(*s->block32))) || + !(s->dpcm_macroblock = av_mallocz(sizeof(*s->dpcm_macroblock)))) + return AVERROR(ENOMEM); + s->dpcm_direction = 0; + /* ac values */ if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base, yc_size)) return AVERROR(ENOMEM); From de29d482f9ee8d9cea9c58a1370ab99028adff3f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 1 Jan 2022 12:30:19 +0100 Subject: [PATCH 836/894] avcodec/mpegvideo: Avoid macro/av_calloc for ordinary allocations Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index af433153f2..e9f2fb212a 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -632,9 +632,9 @@ int ff_mpv_init_context_frame(MpegEncContext *s) if (s->out_format == FMT_H263) { /* cbp values, cbp, ac_pred, pred_dir */ - if (!FF_ALLOCZ_TYPED_ARRAY(s->coded_block_base, y_size + (s->mb_height&1)*2*s->b8_stride) || - !FF_ALLOCZ_TYPED_ARRAY(s->cbp_table, mb_array_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->pred_dir_table, mb_array_size)) + if (!(s->coded_block_base = av_mallocz(y_size + (s->mb_height&1)*2*s->b8_stride)) || + !(s->cbp_table = av_mallocz(mb_array_size)) || + !(s->pred_dir_table = av_mallocz(mb_array_size))) return AVERROR(ENOMEM); s->coded_block = s->coded_block_base + s->b8_stride + 1; } @@ -652,9 +652,9 @@ int ff_mpv_init_context_frame(MpegEncContext *s) } /* which mb is an intra block, init macroblock skip table */ - if (!FF_ALLOC_TYPED_ARRAY(s->mbintra_table, mb_array_size) || + if (!(s->mbintra_table = av_mallocz(mb_array_size)) || // Note the + 1 is for a quicker MPEG-4 slice_end detection - !FF_ALLOCZ_TYPED_ARRAY(s->mbskip_table, mb_array_size + 2)) + !(s->mbskip_table = av_mallocz(mb_array_size + 2))) return AVERROR(ENOMEM); memset(s->mbintra_table, 1, mb_array_size); From 6739bb5a0e749a4936a274ceff7aab2b488393c6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 7 May 2021 22:30:53 +0200 Subject: [PATCH 837/894] avcodec/h263: Move functions only used once to their caller In this case it means moving ff_h263_pred_dc() resp. ff_h263_pred_acdc() to ituh263enc.c resp. ituh263dec.c. Signed-off-by: Andreas Rheinhardt --- libavcodec/h263.c | 128 ---------------------------------------- libavcodec/h263.h | 2 - libavcodec/ituh263dec.c | 89 +++++++++++++++++++++++++++- libavcodec/ituh263enc.c | 43 +++++++++++++- 4 files changed, 130 insertions(+), 132 deletions(-) diff --git a/libavcodec/h263.c b/libavcodec/h263.c index f8fba3c9f4..b30ffaf878 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -102,47 +102,6 @@ void ff_h263_update_motion_val(MpegEncContext * s){ } } -int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) -{ - int x, y, wrap, a, c, pred_dc; - int16_t *dc_val; - - /* find prediction */ - if (n < 4) { - x = 2 * s->mb_x + (n & 1); - y = 2 * s->mb_y + ((n & 2) >> 1); - wrap = s->b8_stride; - dc_val = s->dc_val[0]; - } else { - x = s->mb_x; - y = s->mb_y; - wrap = s->mb_stride; - dc_val = s->dc_val[n - 4 + 1]; - } - /* B C - * A X - */ - a = dc_val[(x - 1) + (y) * wrap]; - c = dc_val[(x) + (y - 1) * wrap]; - - /* No prediction outside GOB boundary */ - if(s->first_slice_line && n!=3){ - if(n!=2) c= 1024; - if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; - } - /* just DC prediction */ - if (a != 1024 && c != 1024) - pred_dc = (a + c) >> 1; - else if (a != 1024) - pred_dc = a; - else - pred_dc = c; - - /* we assume pred is positive */ - *dc_val_ptr = &dc_val[x + y * wrap]; - return pred_dc; -} - void ff_h263_loop_filter(MpegEncContext * s){ int qp_c; const int linesize = s->linesize; @@ -228,93 +187,6 @@ void ff_h263_loop_filter(MpegEncContext * s){ } } -void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) -{ - int x, y, wrap, a, c, pred_dc, scale, i; - int16_t *dc_val, *ac_val, *ac_val1; - - /* find prediction */ - if (n < 4) { - x = 2 * s->mb_x + (n & 1); - y = 2 * s->mb_y + (n>> 1); - wrap = s->b8_stride; - dc_val = s->dc_val[0]; - ac_val = s->ac_val[0][0]; - scale = s->y_dc_scale; - } else { - x = s->mb_x; - y = s->mb_y; - wrap = s->mb_stride; - dc_val = s->dc_val[n - 4 + 1]; - ac_val = s->ac_val[n - 4 + 1][0]; - scale = s->c_dc_scale; - } - - ac_val += ((y) * wrap + (x)) * 16; - ac_val1 = ac_val; - - /* B C - * A X - */ - a = dc_val[(x - 1) + (y) * wrap]; - c = dc_val[(x) + (y - 1) * wrap]; - - /* No prediction outside GOB boundary */ - if(s->first_slice_line && n!=3){ - if(n!=2) c= 1024; - if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; - } - - if (s->ac_pred) { - pred_dc = 1024; - if (s->h263_aic_dir) { - /* left prediction */ - if (a != 1024) { - ac_val -= 16; - for(i=1;i<8;i++) { - block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; - } - pred_dc = a; - } - } else { - /* top prediction */ - if (c != 1024) { - ac_val -= 16 * wrap; - for(i=1;i<8;i++) { - block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; - } - pred_dc = c; - } - } - } else { - /* just DC prediction */ - if (a != 1024 && c != 1024) - pred_dc = (a + c) >> 1; - else if (a != 1024) - pred_dc = a; - else - pred_dc = c; - } - - /* we assume pred is positive */ - block[0]=block[0]*scale + pred_dc; - - if (block[0] < 0) - block[0] = 0; - else - block[0] |= 1; - - /* Update AC/DC tables */ - dc_val[(x) + (y) * wrap] = block[0]; - - /* left copy */ - for(i=1;i<8;i++) - ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; - /* top copy */ - for(i=1;i<8;i++) - ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; -} - int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, int *px, int *py) { diff --git a/libavcodec/h263.h b/libavcodec/h263.h index 84a3a19517..982e545491 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -74,8 +74,6 @@ void ff_h263_loop_filter(MpegEncContext * s); int ff_h263_decode_mba(MpegEncContext *s); void ff_h263_encode_mba(MpegEncContext *s); void ff_init_qscale_tab(MpegEncContext *s); -int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr); -void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n); /** diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 3f982f414f..17af5d7f89 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -439,6 +439,93 @@ static void h263_decode_dquant(MpegEncContext *s){ ff_set_qscale(s, s->qscale); } +static void h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) +{ + int x, y, wrap, a, c, pred_dc, scale; + int16_t *dc_val, *ac_val, *ac_val1; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + (n & 1); + y = 2 * s->mb_y + (n>> 1); + wrap = s->b8_stride; + dc_val = s->dc_val[0]; + ac_val = s->ac_val[0][0]; + scale = s->y_dc_scale; + } else { + x = s->mb_x; + y = s->mb_y; + wrap = s->mb_stride; + dc_val = s->dc_val[n - 4 + 1]; + ac_val = s->ac_val[n - 4 + 1][0]; + scale = s->c_dc_scale; + } + + ac_val += ((y) * wrap + (x)) * 16; + ac_val1 = ac_val; + + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + /* No prediction outside GOB boundary */ + if (s->first_slice_line && n != 3) { + if (n != 2) c= 1024; + if (n != 1 && s->mb_x == s->resync_mb_x) a= 1024; + } + + if (s->ac_pred) { + pred_dc = 1024; + if (s->h263_aic_dir) { + /* left prediction */ + if (a != 1024) { + ac_val -= 16; + for (int i = 1; i < 8; i++) { + block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; + } + pred_dc = a; + } + } else { + /* top prediction */ + if (c != 1024) { + ac_val -= 16 * wrap; + for (int i = 1; i < 8; i++) { + block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; + } + pred_dc = c; + } + } + } else { + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + } + + /* we assume pred is positive */ + block[0] = block[0] * scale + pred_dc; + + if (block[0] < 0) + block[0] = 0; + else + block[0] |= 1; + + /* Update AC/DC tables */ + dc_val[(x) + (y) * wrap] = block[0]; + + /* left copy */ + for (int i = 1; i < 8; i++) + ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; + /* top copy */ + for (int i = 1; i < 8; i++) + ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; +} + static int h263_decode_block(MpegEncContext * s, int16_t * block, int n, int coded) { @@ -579,7 +666,7 @@ retry: } not_coded: if (s->mb_intra && s->h263_aic) { - ff_h263_pred_acdc(s, block, n); + h263_pred_acdc(s, block, n); i = 63; } s->block_last_index[n] = i; diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 79c8c9999e..d944c4879f 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -445,6 +445,47 @@ static void h263p_encode_umotion(PutBitContext *pb, int val) } } +static int h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) +{ + int x, y, wrap, a, c, pred_dc; + int16_t *dc_val; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + (n & 1); + y = 2 * s->mb_y + ((n & 2) >> 1); + wrap = s->b8_stride; + dc_val = s->dc_val[0]; + } else { + x = s->mb_x; + y = s->mb_y; + wrap = s->mb_stride; + dc_val = s->dc_val[n - 4 + 1]; + } + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + /* No prediction outside GOB boundary */ + if (s->first_slice_line && n != 3) { + if (n != 2) c = 1024; + if (n != 1 && s->mb_x == s->resync_mb_x) a = 1024; + } + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + + /* we assume pred is positive */ + *dc_val_ptr = &dc_val[x + y * wrap]; + return pred_dc; +} + void ff_h263_encode_mb(MpegEncContext * s, int16_t block[6][64], int motion_x, int motion_y) @@ -552,7 +593,7 @@ void ff_h263_encode_mb(MpegEncContext * s, if(i<4) scale= s->y_dc_scale; else scale= s->c_dc_scale; - pred_dc = ff_h263_pred_dc(s, i, &dc_ptr[i]); + pred_dc = h263_pred_dc(s, i, &dc_ptr[i]); level -= pred_dc; /* Quant */ if (level >= 0) From f0194e860e33cb60a80305eae2262b2e7977c908 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 06:05:59 +0100 Subject: [PATCH 838/894] avcodec/mpeg4video: Skip unneeded element when parsing picture header Namely, skip some elements that are only useful for a decoder when calling ff_mpeg4_decode_picture_header() from the MPEG-4 parser. In particular, this ensures that the VLCs need no longer be initialized by the parser. Signed-off-by: Andreas Rheinhardt --- libavcodec/h263dec.c | 4 ++-- libavcodec/mpeg4video.h | 3 ++- libavcodec/mpeg4video_parser.c | 4 ++-- libavcodec/mpeg4videodec.c | 18 +++++++++++++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 2682a7f43a..11e80cb9e9 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -507,9 +507,9 @@ retry: GetBitContext gb; if (init_get_bits8(&gb, s->avctx->extradata, s->avctx->extradata_size) >= 0 ) - ff_mpeg4_decode_picture_header(avctx->priv_data, &gb, 1); + ff_mpeg4_decode_picture_header(avctx->priv_data, &gb, 1, 0); } - ret = ff_mpeg4_decode_picture_header(avctx->priv_data, &s->gb, 0); + ret = ff_mpeg4_decode_picture_header(avctx->priv_data, &s->gb, 0, 0); } else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) { ret = ff_intel_h263_decode_picture_header(s); } else if (CONFIG_FLV_DECODER && s->h263_flv) { diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index 3db6f85153..ee8eea7121 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -160,7 +160,8 @@ void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, void ff_set_mpeg4_time(MpegEncContext *s); int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); -int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, int header); +int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int header, int parse_only); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_clean_buffers(MpegEncContext *s); void ff_mpeg4_stuffing(PutBitContext *pbc); diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index c68c966259..9e96619a12 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -100,13 +100,13 @@ static int mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx, if (avctx->extradata_size && pc->first_picture) { init_get_bits(gb, avctx->extradata, avctx->extradata_size * 8); - ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 1); + ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 1, 1); if (ret < 0) av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n"); } init_get_bits(gb, buf, 8 * buf_size); - ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 0); + ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 0, 1); if (s->width && (!avctx->width || !avctx->height || !avctx->coded_width || !avctx->coded_height)) { ret = ff_set_dimensions(avctx, s->width, s->height); diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 34b050db28..ab8d2e8236 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -2844,7 +2844,8 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) return 0; } -static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) +static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int parse_only) { MpegEncContext *s = &ctx->m; int time_incr, time_increment; @@ -3018,6 +3019,12 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } + /* Skip at this point when only parsing since the remaining + * data is not useful for a parser and requires the + * sprite_trajectory VLC to be initialized. */ + if (parse_only) + goto end; + if (s->pict_type == AV_PICTURE_TYPE_S) { if((ctx->vol_sprite_usage == STATIC_SPRITE || ctx->vol_sprite_usage == GMC_SPRITE)) { @@ -3095,6 +3102,8 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) skip_bits(gb, 2); // ref_select_code } } + +end: /* detect buggy encoders which don't set the low_delay flag * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames * easily (although it's buggy too) */ @@ -3214,11 +3223,14 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb) * Decode MPEG-4 headers. * * @param header If set the absence of a VOP is not treated as error; otherwise, it is treated as such. + * @param parse_only If set, things only relevant to a decoder may be skipped; + * furthermore, the VLC tables may be uninitialized. * @return <0 if an error occurred * FRAME_SKIPPED if a not coded VOP is found * 0 else */ -int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, int header) +int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int header, int parse_only) { MpegEncContext *s = &ctx->m; unsigned startcode, v; @@ -3371,7 +3383,7 @@ end: } return decode_studio_vop_header(ctx, gb); } else - return decode_vop_header(ctx, gb); + return decode_vop_header(ctx, gb, parse_only); } av_cold void ff_mpeg4videodec_static_init(void) { From 832ead2ec40392e73422f9a9d3ab1f21ea025207 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 06:12:27 +0100 Subject: [PATCH 839/894] avcodec/mpeg4videodec: Fix data race when initializing VLCs Both the MPEG-4 parser as well as the decoder initialized several VLCs. There is a "static int done = 0;" in order to guard against initializing these multiple times, but this does not work when several threads try to initialize these VLCs concurrently, which can happen when initializing several parsers at the same time (they don't use the global lock that is used for codecs without the FF_CODEC_CAP_INIT_THREADSAFE cap; actually, they don't use any lock at all). Since ff_mpeg4_decode_picture_header() now aborts early when called from the parser, it no longer needs to have these VLCs initialized at all. This commit therefore does exactly this. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg4video.h | 1 - libavcodec/mpeg4video_parser.c | 2 -- libavcodec/mpeg4videodec.c | 50 ++++++++++++++-------------------- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index ee8eea7121..cec8b30c32 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -173,7 +173,6 @@ int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s); int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx); int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx); void ff_mpeg4_init_direct_mv(MpegEncContext *s); -void ff_mpeg4videodec_static_init(void); int ff_mpeg4_workaround_bugs(AVCodecContext *avctx); int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size); diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index 9e96619a12..1f89bae490 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -129,8 +129,6 @@ static av_cold int mpeg4video_parse_init(AVCodecParserContext *s) { struct Mp4vParseContext *pc = s->priv_data; - ff_mpeg4videodec_static_init(); - pc->first_picture = 1; pc->dec_ctx.m.quant_precision = 5; pc->dec_ctx.m.slice_context_count = 1; diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index ab8d2e8236..325593a795 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3386,34 +3386,6 @@ end: return decode_vop_header(ctx, gb, parse_only); } -av_cold void ff_mpeg4videodec_static_init(void) { - static int done = 0; - - if (!done) { - static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; - - ff_mpeg4_init_rl_intra(); - ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]); - ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]); - INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); - INIT_VLC_RL(ff_rvlc_rl_inter, 1072); - INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072); - INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */, - &ff_mpeg4_DCtab_lum[0][1], 2, 1, - &ff_mpeg4_DCtab_lum[0][0], 2, 1, 512); - INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */, - &ff_mpeg4_DCtab_chrom[0][1], 2, 1, - &ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512); - INIT_VLC_STATIC_FROM_LENGTHS(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15, - ff_sprite_trajectory_lens, 1, - NULL, 0, 0, 0, 0, 128); - INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4, - &ff_mb_type_b_tab[0][1], 2, 1, - &ff_mb_type_b_tab[0][0], 2, 1, 16); - done = 1; - } -} - int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size) { Mpeg4DecContext *ctx = avctx->priv_data; @@ -3525,6 +3497,8 @@ static int mpeg4_update_thread_context_for_user(AVCodecContext *dst, static av_cold void mpeg4_init_static(void) { + static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; + INIT_VLC_STATIC_FROM_LENGTHS(&studio_luma_dc, STUDIO_INTRA_BITS, 19, &ff_mpeg4_studio_dc_luma[0][1], 2, &ff_mpeg4_studio_dc_luma[0][0], 2, 1, @@ -3547,7 +3521,25 @@ static av_cold void mpeg4_init_static(void) 0, INIT_VLC_STATIC_OVERLONG, NULL); offset += studio_intra_tab[i].table_size; } - ff_mpeg4videodec_static_init(); + + ff_mpeg4_init_rl_intra(); + ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]); + ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]); + INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); + INIT_VLC_RL(ff_rvlc_rl_inter, 1072); + INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072); + INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */, + &ff_mpeg4_DCtab_lum[0][1], 2, 1, + &ff_mpeg4_DCtab_lum[0][0], 2, 1, 512); + INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */, + &ff_mpeg4_DCtab_chrom[0][1], 2, 1, + &ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512); + INIT_VLC_STATIC_FROM_LENGTHS(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15, + ff_sprite_trajectory_lens, 1, + NULL, 0, 0, 0, 0, 128); + INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4, + &ff_mb_type_b_tab[0][1], 2, 1, + &ff_mb_type_b_tab[0][0], 2, 1, 16); } static av_cold int decode_init(AVCodecContext *avctx) From 938251c878d46aef001da2527fb7234b9f2f83ea Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 8 May 2021 01:11:06 +0200 Subject: [PATCH 840/894] avcodec/rl: Don't pretend ff_rl_init() initializes a RLTable twice It can't any longer, because all users of ff_rl_init() are now behind ff_thread_once() or the global codec lock. Therefore the check for whether the RLTable is already initialized can be removed; as can the stack buffers that existed to make sure that nothing is ever set to a value different from its final value. Similarly, it is not necessary to check whether the VLCs associated with the RLTable are already initialized (they aren't). Signed-off-by: Andreas Rheinhardt --- libavcodec/rl.c | 20 ++++++-------------- libavcodec/rl.h | 9 +++------ 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/libavcodec/rl.c b/libavcodec/rl.c index fab96d63a1..4ce003ccf4 100644 --- a/libavcodec/rl.c +++ b/libavcodec/rl.c @@ -27,16 +27,13 @@ av_cold void ff_rl_init(RLTable *rl, uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3]) { - int8_t max_level[MAX_RUN + 1], max_run[MAX_LEVEL + 1]; - uint8_t index_run[MAX_RUN + 1]; int last, run, level, start, end, i; - /* If rl->max_level[0] is set, this RLTable has already been initialized */ - if (rl->max_level[0]) - return; - /* compute max_level[], max_run[] and index_run[] */ for (last = 0; last < 2; last++) { + int8_t *max_level = static_store[last]; + int8_t *max_run = static_store[last] + MAX_RUN + 1; + uint8_t *index_run = static_store[last] + MAX_RUN + 1 + MAX_LEVEL + 1; if (last == 0) { start = 0; end = rl->last; @@ -45,8 +42,6 @@ av_cold void ff_rl_init(RLTable *rl, end = rl->n; } - memset(max_level, 0, MAX_RUN + 1); - memset(max_run, 0, MAX_LEVEL + 1); memset(index_run, rl->n, MAX_RUN + 1); for (i = start; i < end; i++) { run = rl->table_run[i]; @@ -58,12 +53,9 @@ av_cold void ff_rl_init(RLTable *rl, if (run > max_run[level]) max_run[level] = run; } - rl->max_level[last] = static_store[last]; - memcpy(rl->max_level[last], max_level, MAX_RUN + 1); - rl->max_run[last] = static_store[last] + MAX_RUN + 1; - memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); - rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; - memcpy(rl->index_run[last], index_run, MAX_RUN + 1); + rl->max_level[last] = max_level; + rl->max_run[last] = max_run; + rl->index_run[last] = index_run; } } diff --git a/libavcodec/rl.h b/libavcodec/rl.h index 5aae698e31..07e3da5003 100644 --- a/libavcodec/rl.h +++ b/libavcodec/rl.h @@ -72,15 +72,12 @@ void ff_rl_init_vlc(RLTable *rl, unsigned static_size); #define INIT_VLC_RL(rl, static_size)\ {\ - int q;\ static RL_VLC_ELEM rl_vlc_table[32][static_size];\ \ - if(!rl.rl_vlc[0]){\ - for(q=0; q<32; q++)\ - rl.rl_vlc[q]= rl_vlc_table[q];\ + for (int q = 0; q < 32; q++) \ + rl.rl_vlc[q] = rl_vlc_table[q]; \ \ - ff_rl_init_vlc(&rl, static_size);\ - }\ + ff_rl_init_vlc(&rl, static_size); \ } #define INIT_FIRST_VLC_RL(rl, static_size) \ From e60debb93efc0bb76475682bc26e7a0645241e2f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 07:43:59 +0100 Subject: [PATCH 841/894] avcodec/bitstream: Don't pretend VLCs to be initialized concurrently Since the MPEG-4 parser no longer initializes some MPEG-4 VLCs, no VLC is initialized concurrently by multiple threads (initializing static VLCs is guarded by locks and nonstatic VLCs never posed an issue in this regard). So remove the code in bitstream.c that only exists because of this possibility. Signed-off-by: Andreas Rheinhardt --- libavcodec/bitstream.c | 43 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index 1f77cafae6..2dd0226614 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -142,21 +142,16 @@ typedef struct VLCcode { uint32_t code; } VLCcode; -static int vlc_common_init(VLC *vlc_arg, int nb_bits, int nb_codes, - VLC **vlc, VLC *localvlc, VLCcode **buf, - int flags) +static int vlc_common_init(VLC *vlc, int nb_bits, int nb_codes, + VLCcode **buf, int flags) { - *vlc = vlc_arg; - (*vlc)->bits = nb_bits; + vlc->bits = nb_bits; + vlc->table_size = 0; if (flags & INIT_VLC_USE_NEW_STATIC) { av_assert0(nb_codes <= LOCALBUF_ELEMS); - *localvlc = *vlc_arg; - *vlc = localvlc; - (*vlc)->table_size = 0; } else { - (*vlc)->table = NULL; - (*vlc)->table_allocated = 0; - (*vlc)->table_size = 0; + vlc->table = NULL; + vlc->table_allocated = 0; } if (nb_codes > LOCALBUF_ELEMS) { *buf = av_malloc_array(nb_codes, sizeof(VLCcode)); @@ -191,8 +186,8 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, { int table_size, table_index, index, code_prefix, symbol, subtable_bits; int i, j, k, n, nb, inc; + VLC_TYPE (*table)[2]; uint32_t code; - volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent an internal compiler error in gcc 4.2 if (table_nb_bits > 30) return AVERROR(EINVAL); @@ -201,7 +196,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, ff_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); if (table_index < 0) return table_index; - table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; + table = &vlc->table[table_index]; /* first pass: map codes and compute auxiliary table sizes */ for (i = 0; i < nb_codes; i++) { @@ -257,7 +252,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, if (index < 0) return index; /* note: realloc has been done, so reload tables */ - table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; + table = &vlc->table[table_index]; table[j][0] = index; //code if (table[j][0] != index) { avpriv_request_sample(NULL, "strange codes"); @@ -276,7 +271,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, } static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, - int flags, VLC *vlc_arg, VLCcode localbuf[LOCALBUF_ELEMS]) + int flags, VLCcode localbuf[LOCALBUF_ELEMS]) { int ret = build_table(vlc, nb_bits, nb_codes, codes, flags); @@ -285,7 +280,6 @@ static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, !(flags & (INIT_VLC_STATIC_OVERLONG & ~INIT_VLC_USE_NEW_STATIC))) av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); av_assert0(ret >= 0); - *vlc_arg = *vlc; } else { if (codes != localbuf) av_free(codes); @@ -320,7 +314,7 @@ static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, 'wrap' and 'size' make it possible to use any memory configuration and types (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables. */ -int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, +int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, const void *bits, int bits_wrap, int bits_size, const void *codes, int codes_wrap, int codes_size, const void *symbols, int symbols_wrap, int symbols_size, @@ -328,10 +322,8 @@ int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, { VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; int i, j, ret; - VLC localvlc, *vlc; - ret = vlc_common_init(vlc_arg, nb_bits, nb_codes, &vlc, &localvlc, - &buf, flags); + ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret; @@ -375,21 +367,19 @@ int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, nb_codes = j; return vlc_common_end(vlc, nb_bits, nb_codes, buf, - flags, vlc_arg, localbuf); + flags, localbuf); } -int ff_init_vlc_from_lengths(VLC *vlc_arg, int nb_bits, int nb_codes, +int ff_init_vlc_from_lengths(VLC *vlc, int nb_bits, int nb_codes, const int8_t *lens, int lens_wrap, const void *symbols, int symbols_wrap, int symbols_size, int offset, int flags, void *logctx) { VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; - VLC localvlc, *vlc; uint64_t code; int ret, j, len_max = FFMIN(32, 3 * nb_bits); - ret = vlc_common_init(vlc_arg, nb_bits, nb_codes, &vlc, &localvlc, - &buf, flags); + ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret; @@ -420,8 +410,7 @@ int ff_init_vlc_from_lengths(VLC *vlc_arg, int nb_bits, int nb_codes, goto fail; } } - return vlc_common_end(vlc, nb_bits, j, buf, - flags, vlc_arg, localbuf); + return vlc_common_end(vlc, nb_bits, j, buf, flags, localbuf); fail: if (buf != localbuf) av_free(buf); From a88a141c1791b448f2c327e6bdd9491a4439efc2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 09:21:05 +0100 Subject: [PATCH 842/894] avcodec: Remove unnecessary h263.h inclusions Signed-off-by: Andreas Rheinhardt --- libavcodec/flvenc.c | 1 - libavcodec/h261dec.c | 1 - libavcodec/h261enc.c | 1 - libavcodec/msmpeg4.c | 1 - libavcodec/msmpeg4data.c | 2 +- libavcodec/snow.c | 1 - libavcodec/snowdec.c | 2 -- libavcodec/svq1dec.c | 2 +- 8 files changed, 2 insertions(+), 9 deletions(-) diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index 614ef20243..158b399c40 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -19,7 +19,6 @@ */ #include "flv.h" -#include "h263.h" #include "h263data.h" #include "mpegvideo.h" #include "mpegvideodata.h" diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 80ec1c8814..2fd8d94df1 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -31,7 +31,6 @@ #include "mpeg_er.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" #include "h261.h" #include "internal.h" diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 79f680f81d..af65c1f3b1 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -31,7 +31,6 @@ #include "avcodec.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" #include "h261.h" #include "mpegvideodata.h" diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 16b6f18950..e76aec6dfc 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -34,7 +34,6 @@ #include "mpegvideo.h" #include "msmpeg4.h" #include "libavutil/x86/asm.h" -#include "h263.h" #include "mpeg4video.h" #include "msmpeg4data.h" #include "mpegvideodata.h" diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c index 890aeb5670..a3a8144664 100644 --- a/libavcodec/msmpeg4data.c +++ b/libavcodec/msmpeg4data.c @@ -27,7 +27,7 @@ * MSMPEG4 data tables. */ -#include "h263.h" +#include "h263data.h" #include "mpeg4video.h" #include "msmpeg4data.h" diff --git a/libavcodec/snow.c b/libavcodec/snow.c index e0fb58042c..0a500695ce 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -31,7 +31,6 @@ #include "rangecoder.h" #include "mathops.h" -#include "h263.h" void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index cd2265aba1..d54036e02b 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -29,8 +29,6 @@ #include "rangecoder.h" #include "mathops.h" -#include "h263.h" - static av_always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){ Plane *p= &s->plane[plane_index]; const int mb_w= s->b_width << s->block_max_depth; diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c index a67d1866b6..a2b3f71c07 100644 --- a/libavcodec/svq1dec.c +++ b/libavcodec/svq1dec.c @@ -37,7 +37,7 @@ #include "avcodec.h" #include "get_bits.h" -#include "h263.h" +#include "h263data.h" #include "hpeldsp.h" #include "internal.h" #include "mathops.h" From ebf1d0f4bb7e849a4a4481eeba3a96c1df674308 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 5 Jan 2022 22:47:45 +0100 Subject: [PATCH 843/894] avcodec/avcodec: Remove outdated comment avcodec_open2() is supposed to be thread-safe (those codecs whose init functions are not thread-safe are guarded by a global lock). Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavcodec/avcodec.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7ee8bc2b7c..ec1a0566a4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2384,8 +2384,6 @@ int avcodec_parameters_to_context(AVCodecContext *codec, * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for * retrieving a codec. * - * @warning This function is not thread safe! - * * @note Always call this function before using decoding routines (such as * @ref avcodec_receive_frame()). * From df701ed0b582a6b5c763310b4225446089cbcfb1 Mon Sep 17 00:00:00 2001 From: Ming Qian Date: Tue, 4 Jan 2022 17:08:30 +0800 Subject: [PATCH 844/894] avcodec/v4l2_context: don't reinit output queue on dynamic resolution change event Reference: linux/Documentation/userspace-api/media/v4l/dev-decoder.rst "During the resolution change sequence, the OUTPUT queue must remain streaming. Calling VIDIOC_STREAMOFF() on the OUTPUT queue would abort the sequence and initiate a seek. In principle, the OUTPUT queue operates separately from the CAPTURE queue and this remains true for the duration of the entire resolution change sequence as well." Reviewed-by: Andriy Gelman Signed-off-by: Ming Qian --- libavcodec/v4l2_context.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index ff1ea8e57b..dda5157698 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -162,9 +162,8 @@ static int v4l2_handle_event(V4L2Context *ctx) { V4L2m2mContext *s = ctx_to_m2mctx(ctx); struct v4l2_format cap_fmt = s->capture.format; - struct v4l2_format out_fmt = s->output.format; struct v4l2_event evt = { 0 }; - int full_reinit, reinit, ret; + int reinit, ret; ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); if (ret < 0) { @@ -180,25 +179,12 @@ static int v4l2_handle_event(V4L2Context *ctx) if (evt.type != V4L2_EVENT_SOURCE_CHANGE) return 0; - ret = ioctl(s->fd, VIDIOC_G_FMT, &out_fmt); - if (ret) { - av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->output.name); - return 0; - } - ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt); if (ret) { av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->capture.name); return 0; } - full_reinit = v4l2_resolution_changed(&s->output, &out_fmt); - if (full_reinit) { - s->output.height = v4l2_get_height(&out_fmt); - s->output.width = v4l2_get_width(&out_fmt); - s->output.sample_aspect_ratio = v4l2_get_sar(&s->output); - } - reinit = v4l2_resolution_changed(&s->capture, &cap_fmt); if (reinit) { s->capture.height = v4l2_get_height(&cap_fmt); @@ -206,18 +192,9 @@ static int v4l2_handle_event(V4L2Context *ctx) s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); } - if (full_reinit || reinit) + if (reinit) s->reinit = 1; - if (full_reinit) { - ret = ff_v4l2_m2m_codec_full_reinit(s); - if (ret) { - av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit\n"); - return AVERROR(EINVAL); - } - goto reinit_run; - } - if (reinit) { if (s->avctx) ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); From 3fc72c9fc16df3b7edc329ed9eeaaa1e65976c33 Mon Sep 17 00:00:00 2001 From: Ming Qian Date: Tue, 4 Jan 2022 17:08:32 +0800 Subject: [PATCH 845/894] avcodec/v4l2_context: send start decode command after dynamic resolution change event Fixes decoding of sample https://streams.videolan.org/ffmpeg/incoming/720p60.mp4 on RPi4 after kernel driver commit: staging: bcm2835-codec: Format changed should trigger drain Reference: linux/Documentation/userspace-api/media/v4l/dev-decoder.rst "A source change triggers an implicit decoder drain, similar to the explicit Drain sequence. The decoder is stopped after it completes. The decoding process must be resumed with either a pair of calls to VIDIOC_STREAMOFF and VIDIOC_STREAMON on the CAPTURE queue, or a call to VIDIOC_DECODER_CMD with the V4L2_DEC_CMD_START command." Reviewed-by: Andriy Gelman Signed-off-by: Ming Qian --- libavcodec/v4l2_context.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index dda5157698..a181f884d2 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -153,6 +153,21 @@ static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_upd } } +static int v4l2_start_decode(V4L2Context *ctx) +{ + struct v4l2_decoder_cmd cmd = { + .cmd = V4L2_DEC_CMD_START, + .flags = 0, + }; + int ret; + + ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd); + if (ret) + return AVERROR(errno); + + return 0; +} + /** * handle resolution change event and end of stream event * returns 1 if reinit was successful, negative if it failed @@ -190,6 +205,9 @@ static int v4l2_handle_event(V4L2Context *ctx) s->capture.height = v4l2_get_height(&cap_fmt); s->capture.width = v4l2_get_width(&cap_fmt); s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); + } else { + v4l2_start_decode(ctx); + return 0; } if (reinit) From 47c4df2203f774f6a62391e1de770cf5b9dddcbd Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 25 Nov 2021 23:33:10 +0100 Subject: [PATCH 846/894] avformat/mxfdec: support MCA audio information Channel reordering is removed from this patch because the new channel layout API will support it properly. Signed-off-by: Marton Balint --- libavformat/mxf.h | 3 + libavformat/mxfdec.c | 288 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 285 insertions(+), 6 deletions(-) diff --git a/libavformat/mxf.h b/libavformat/mxf.h index fe9c52732c..d53a16df51 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -50,6 +50,9 @@ enum MXFMetadataSetType { TaggedValue, TapeDescriptor, AVCSubDescriptor, + AudioChannelLabelSubDescriptor, + SoundfieldGroupLabelSubDescriptor, + GroupOfSoundfieldGroupsLabelSubDescriptor, }; enum MXFFrameLayout { diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 1d50198279..b85c10bf19 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -51,11 +51,14 @@ #include "libavutil/mastering_display_metadata.h" #include "libavutil/mathematics.h" #include "libavcodec/bytestream.h" +#include "libavcodec/internal.h" +#include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/parseutils.h" #include "libavutil/timecode.h" #include "libavutil/opt.h" #include "avformat.h" +#include "avlanguage.h" #include "internal.h" #include "mxf.h" @@ -177,6 +180,8 @@ typedef struct { int body_sid; MXFWrappingScheme wrapping; int edit_units_per_packet; /* how many edit units to read at a time (PCM, ClipWrapped) */ + int require_reordering; + int channel_ordering[FF_SANE_NB_CHANNELS]; } MXFTrack; typedef struct MXFDescriptor { @@ -205,6 +210,8 @@ typedef struct MXFDescriptor { unsigned int vert_subsampling; UID *file_descriptors_refs; int file_descriptors_count; + UID *sub_descriptors_refs; + int sub_descriptors_count; int linked_track_id; uint8_t *extradata; int extradata_size; @@ -217,6 +224,18 @@ typedef struct MXFDescriptor { size_t coll_size; } MXFDescriptor; +typedef struct MXFMCASubDescriptor { + MXFMetadataSet meta; + UID uid; + UID mca_link_id; + UID soundfield_group_link_id; + UID *group_of_soundfield_groups_link_id_refs; + int group_of_soundfield_groups_link_id_count; + UID mca_label_dictionary_id; + int mca_channel_id; + char *language; +} MXFMCASubDescriptor; + typedef struct MXFIndexTableSegment { MXFMetadataSet meta; int edit_unit_byte_count; @@ -311,6 +330,7 @@ static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; static const uint8_t mxf_apple_coll_prefix[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01 }; + /* complete keys to match */ static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; @@ -323,6 +343,17 @@ static const uint8_t mxf_indirect_value_utf16be[] = { 0x42,0x01,0x10,0x static const uint8_t mxf_apple_coll_max_cll[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x01 }; static const uint8_t mxf_apple_coll_max_fall[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x02 }; +static const uint8_t mxf_mca_label_dictionary_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x01,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_tag_symbol[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x02,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_tag_name[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x03,0x00,0x00,0x00 }; +static const uint8_t mxf_group_of_soundfield_groups_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x04,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x05,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_channel_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x04,0x0a,0x00,0x00,0x00,0x00 }; +static const uint8_t mxf_soundfield_group_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x06,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_rfc5646_spoken_language[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0d,0x03,0x01,0x01,0x02,0x03,0x15,0x00,0x00 }; + +static const uint8_t mxf_sub_descriptor[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00 }; + static const uint8_t mxf_mastering_display_prefix[13] = { FF_MXF_MasteringDisplay_PREFIX }; static const uint8_t mxf_mastering_display_uls[4][16] = { FF_MXF_MasteringDisplayPrimaries, @@ -343,6 +374,13 @@ static void mxf_free_metadataset(MXFMetadataSet **ctx, int freectx) av_freep(&((MXFDescriptor *)*ctx)->mastering); av_freep(&((MXFDescriptor *)*ctx)->coll); av_freep(&((MXFDescriptor *)*ctx)->file_descriptors_refs); + av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs); + break; + case AudioChannelLabelSubDescriptor: + case SoundfieldGroupLabelSubDescriptor: + case GroupOfSoundfieldGroupsLabelSubDescriptor: + av_freep(&((MXFMCASubDescriptor *)*ctx)->language); + av_freep(&((MXFMCASubDescriptor *)*ctx)->group_of_soundfield_groups_link_id_refs); break; case Sequence: av_freep(&((MXFSequence *)*ctx)->structural_components_refs); @@ -906,6 +944,30 @@ static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count) return 0; } +static inline int mxf_read_us_ascii_string(AVIOContext *pb, int size, char** str) +{ + int ret; + size_t buf_size; + + if (size < 0 || size > INT_MAX - 1) + return AVERROR(EINVAL); + + buf_size = size + 1; + av_free(*str); + *str = av_malloc(buf_size); + if (!*str) + return AVERROR(ENOMEM); + + ret = avio_get_str(pb, size, *str, buf_size); + + if (ret < 0) { + av_freep(str); + return ret; + } + + return ret; +} + static inline int mxf_read_utf16_string(AVIOContext *pb, int size, char** str, int be) { int ret; @@ -1363,11 +1425,40 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int descriptor->coll->MaxFALL = avio_rb16(pb); } } + + if (IS_KLV_KEY(uid, mxf_sub_descriptor)) + return mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, &descriptor->sub_descriptors_count); + break; } return 0; } +static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) +{ + MXFMCASubDescriptor *mca_sub_descriptor = arg; + + if (IS_KLV_KEY(uid, mxf_mca_label_dictionary_id)) + avio_read(pb, mca_sub_descriptor->mca_label_dictionary_id, 16); + + if (IS_KLV_KEY(uid, mxf_mca_link_id)) + avio_read(pb, mca_sub_descriptor->mca_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_soundfield_group_link_id)) + avio_read(pb, mca_sub_descriptor->soundfield_group_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_group_of_soundfield_groups_link_id)) + return mxf_read_strong_ref_array(pb, &mca_sub_descriptor->group_of_soundfield_groups_link_id_refs, &mca_sub_descriptor->group_of_soundfield_groups_link_id_count); + + if (IS_KLV_KEY(uid, mxf_mca_channel_id)) + mca_sub_descriptor->mca_channel_id = avio_rb32(pb); + + if (IS_KLV_KEY(uid, mxf_mca_rfc5646_spoken_language)) + return mxf_read_us_ascii_string(pb, size, &mca_sub_descriptor->language); + + return 0; +} + static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size) { MXFTaggedValue *tagged_value = arg; @@ -1497,6 +1588,52 @@ static const MXFCodecUL mxf_data_essence_container_uls[] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; +typedef struct MXFChannelOrderingUL { + UID uid; + uint64_t layout_mask; + enum AVAudioServiceType service_type; +} MXFChannelOrderingUL; + +static const MXFChannelOrderingUL mxf_channel_ordering[] = { + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x02,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x03,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x04,0x00,0x00,0x00,0x00 }, AV_CH_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Low Frequency Effects + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x05,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x06,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x07,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x08,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x09,0x00,0x00,0x00,0x00 }, AV_CH_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0a,0x00,0x00,0x00,0x00 }, AV_CH_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0b,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_LEFT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0c,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_RIGHT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0d,0x00,0x00,0x00,0x00 }, AV_CH_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0e,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, // Hearing impaired audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0f,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, // Visually impaired narrative audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x20,0x03,0x00,0x00,0x00 }, AV_CH_STEREO_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Total + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x20,0x04,0x00,0x00,0x00 }, AV_CH_STEREO_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Total + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x01,0x00,0x00 }, AV_CH_TOP_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x02,0x00,0x00 }, AV_CH_TOP_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x03,0x00,0x00 }, AV_CH_TOP_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x04,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x05,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x06,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x07,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x08,0x00,0x00 }, AV_CH_TOP_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x09,0x00,0x00 }, AV_CH_TOP_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0a,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0b,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0c,0x00,0x00 }, AV_CH_TOP_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0d,0x00,0x00 }, AV_CH_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Front Subwoofer + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0e,0x00,0x00 }, AV_CH_LOW_FREQUENCY_2, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Front Subwoofer + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0f,0x00,0x00 }, AV_CH_TOP_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x10,0x00,0x00 }, AV_CH_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x11,0x00,0x00 }, AV_CH_BOTTOM_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Below + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x12,0x00,0x00 }, AV_CH_BOTTOM_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Below + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x13,0x00,0x00 }, AV_CH_BOTTOM_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Below + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, +}; + static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul) { int val; @@ -2295,6 +2432,139 @@ static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *des return AVCOL_RANGE_UNSPECIFIED; } +static int is_pcm(enum AVCodecID codec_id) +{ + /* we only care about "normal" PCM codecs until we get samples */ + return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD; +} + +static int set_language(AVFormatContext *s, const char *rfc5646, AVDictionary **met) +{ + // language abbr should contain at least 2 chars + if (rfc5646 && strlen(rfc5646) > 1) { + char primary_tag[4] = + {rfc5646[0], rfc5646[1], rfc5646[2] != '-' ? rfc5646[2] : '\0', '\0'}; + + const char *iso6392 = ff_convert_lang_to(primary_tag, + AV_LANG_ISO639_2_BIBL); + if (iso6392) + return(av_dict_set(met, "language", iso6392, 0)); + } + return 0; +} + +static MXFMCASubDescriptor *find_mca_link_id(MXFContext *mxf, enum MXFMetadataSetType type, UID *mca_link_id) +{ + for (int k = 0; k < mxf->metadata_sets_count; k++) { + MXFMCASubDescriptor *group = (MXFMCASubDescriptor*)mxf->metadata_sets[k]; + if (group->meta.type == type && !memcmp(&group->mca_link_id, mca_link_id, 16)) + return group; + } + return NULL; +} + +static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescriptor *descriptor, AVStream *st) +{ + uint64_t routing[FF_SANE_NB_CHANNELS] = {0}; + char *language = NULL; + int ambigous_language = 0; + enum AVAudioServiceType service_type = AV_AUDIO_SERVICE_TYPE_NB; + int ambigous_service_type = 0; + int has_channel_label = 0; + + for (int i = 0; i < descriptor->sub_descriptors_count; i++) { + char *channel_language; + + MXFMCASubDescriptor *label = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], AudioChannelLabelSubDescriptor); + if (label == NULL) + continue; + + has_channel_label = 1; + for (const MXFChannelOrderingUL* channel_ordering = mxf_channel_ordering; channel_ordering->uid[0]; channel_ordering++) { + if (IS_KLV_KEY(channel_ordering->uid, label->mca_label_dictionary_id)) { + int target_channel = label->mca_channel_id; + if (target_channel == 0 && descriptor->channels == 1) + target_channel = 1; + if (target_channel <= 0 || target_channel > descriptor->channels) { + av_log(mxf->fc, AV_LOG_ERROR, "AudioChannelLabelSubDescriptor has invalid MCA channel ID %d\n", target_channel); + return AVERROR_INVALIDDATA; + } + routing[target_channel - 1] = channel_ordering->layout_mask; + if (service_type == AV_AUDIO_SERVICE_TYPE_NB) + service_type = channel_ordering->service_type; + else if (service_type != channel_ordering->service_type) + ambigous_service_type = 1; + break; + } + } + + channel_language = label->language; + if (!channel_language) { + MXFMCASubDescriptor *group = find_mca_link_id(mxf, SoundfieldGroupLabelSubDescriptor, &label->soundfield_group_link_id); + if (group) { + channel_language = group->language; + if (!channel_language && group->group_of_soundfield_groups_link_id_count) { + MXFMCASubDescriptor *supergroup = find_mca_link_id(mxf, GroupOfSoundfieldGroupsLabelSubDescriptor, + group->group_of_soundfield_groups_link_id_refs); + if (supergroup) + channel_language = supergroup->language; + } + } + } + if (channel_language) { + if (language && strcmp(language, channel_language)) + ambigous_language = 1; + else + language = channel_language; + } + } + + if (language && !ambigous_language) { + int ret = set_language(mxf->fc, language, &st->metadata); + if (ret < 0) + return ret; + } + + if (service_type != AV_AUDIO_SERVICE_TYPE_NB && service_type != AV_AUDIO_SERVICE_TYPE_MAIN && !ambigous_service_type) { + enum AVAudioServiceType *ast; + uint8_t* side_data = av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, sizeof(*ast)); + if (!side_data) + return AVERROR(ENOMEM); + ast = (enum AVAudioServiceType*)side_data; + *ast = service_type; + } + + if (has_channel_label) { + uint64_t channel_layout = 0; + + for (int i = 0; i < descriptor->channels; i++) { + if (!routing[i]) { + av_log(mxf->fc, AV_LOG_WARNING, "Designation of audio channel %d in stream #%d is unknown or unsupported, " + "falling back to unknown channel layout\n", st->index, i); + return 0; + } + if (channel_layout & routing[i]) { + av_log(mxf->fc, AV_LOG_WARNING, "%s audio channel is used multiple times in stream #%d, " + "falling back to unknown channel layout\n", + av_get_channel_name(routing[i]), st->index); + return 0; + } + if (routing[i] < channel_layout) { + av_log(mxf->fc, AV_LOG_WARNING, "stream #%d is not in in native channel order, " + "falling back to unknown channel layout\n", st->index); + return 0; + } + channel_layout |= routing[i]; + } + + av_assert0(descriptor->channels == av_get_channel_layout_nb_channels(channel_layout)); + + st->codecpar->channel_layout = channel_layout; + } + + return 0; +} + static int mxf_parse_structural_metadata(MXFContext *mxf) { MXFPackage *material_package = NULL; @@ -2691,6 +2961,15 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) sti->need_parsing = AVSTREAM_PARSE_FULL; } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); + + if (descriptor->channels <= 0 || descriptor->channels >= FF_SANE_NB_CHANNELS) { + av_log(mxf->fc, AV_LOG_ERROR, "Invalid number of channels %d, must be less than %d\n", descriptor->channels, FF_SANE_NB_CHANNELS); + return AVERROR_INVALIDDATA; + } + + ret = parse_mca_labels(mxf, source_track, descriptor, st); + if (ret < 0) + return ret; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { enum AVMediaType type; container_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul); @@ -2891,6 +3170,9 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* VANC/VBI - SMPTE 436M */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5e,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2AudioDescriptor */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x64,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* DC Timed Text Descriptor */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6b,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), AudioChannelLabelSubDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6c,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), SoundfieldGroupLabelSubDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6d,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), GroupOfSoundfieldGroupsLabelSubDescriptor }, { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent }, @@ -3190,12 +3472,6 @@ static void mxf_compute_essence_containers(AVFormatContext *s) } } -static int is_pcm(enum AVCodecID codec_id) -{ - /* we only care about "normal" PCM codecs until we get samples */ - return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD; -} - static MXFIndexTable *mxf_find_index_table(MXFContext *mxf, int index_sid) { int i; From ae690d5cf51d8b1b09f8ed6799041311cfa57a6b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 1 Jan 2022 20:05:59 +0100 Subject: [PATCH 847/894] avformat/imfdec: do not use filesize when reading XML file Signed-off-by: Marton Balint --- libavformat/imfdec.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index 023f3556f6..566a0fb792 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -73,8 +73,6 @@ #include #include -#define MAX_BPRINT_READ_SIZE (UINT_MAX - 1) -#define DEFAULT_ASSETMAP_SIZE 8 * 1024 #define AVRATIONAL_FORMAT "%d/%d" #define AVRATIONAL_ARG(rational) rational.num, rational.den @@ -279,7 +277,6 @@ static int parse_assetmap(AVFormatContext *s, const char *url) const char *base_url; char *tmp_str = NULL; int ret; - int64_t filesize; av_log(s, AV_LOG_DEBUG, "Asset Map URL: %s\n", url); @@ -289,13 +286,10 @@ static int parse_assetmap(AVFormatContext *s, const char *url) if (ret < 0) return ret; - filesize = avio_size(in); - filesize = filesize > 0 ? filesize : DEFAULT_ASSETMAP_SIZE; + av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer length - av_bprint_init(&buf, filesize + 1, AV_BPRINT_SIZE_UNLIMITED); - - ret = avio_read_to_bprint(in, &buf, MAX_BPRINT_READ_SIZE); - if (ret < 0 || !avio_feof(in) || buf.len == 0) { + ret = avio_read_to_bprint(in, &buf, SIZE_MAX); + if (ret < 0 || !avio_feof(in)) { av_log(s, AV_LOG_ERROR, "Unable to read to asset map '%s'\n", url); if (ret == 0) ret = AVERROR_INVALIDDATA; @@ -311,8 +305,7 @@ static int parse_assetmap(AVFormatContext *s, const char *url) } base_url = av_dirname(tmp_str); - filesize = buf.len; - doc = xmlReadMemory(buf.str, filesize, url, NULL, 0); + doc = xmlReadMemory(buf.str, buf.len, url, NULL, 0); ret = parse_imf_asset_map_from_xml_dom(s, doc, &c->asset_locator_map, base_url); if (!ret) From 22dc472d844683524c4547706173dba40d835888 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 1 Jan 2022 20:08:13 +0100 Subject: [PATCH 848/894] avformat/dashdec: do not use filesize when reading XML file Signed-off-by: Marton Balint --- libavformat/dashdec.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 797fe74157..0d21989e42 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -30,8 +30,6 @@ #include "dash.h" #define INITIAL_BUFFER_SIZE 32768 -#define MAX_BPRINT_READ_SIZE (UINT_MAX - 1) -#define DEFAULT_MANIFEST_SIZE 8 * 1024 struct fragment { int64_t url_offset; @@ -1195,7 +1193,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) DASHContext *c = s->priv_data; int ret = 0; int close_in = 0; - int64_t filesize = 0; AVBPrint buf; AVDictionary *opts = NULL; xmlDoc *doc = NULL; @@ -1226,26 +1223,17 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, (uint8_t**)&c->base_url) < 0) c->base_url = av_strdup(url); - filesize = avio_size(in); - filesize = filesize > 0 ? filesize : DEFAULT_MANIFEST_SIZE; + av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer bufsize - if (filesize > MAX_BPRINT_READ_SIZE) { - av_log(s, AV_LOG_ERROR, "Manifest too large: %"PRId64"\n", filesize); - return AVERROR_INVALIDDATA; - } - - av_bprint_init(&buf, filesize + 1, AV_BPRINT_SIZE_UNLIMITED); - - if ((ret = avio_read_to_bprint(in, &buf, MAX_BPRINT_READ_SIZE)) < 0 || - !avio_feof(in) || - (filesize = buf.len) == 0) { + if ((ret = avio_read_to_bprint(in, &buf, SIZE_MAX)) < 0 || + !avio_feof(in)) { av_log(s, AV_LOG_ERROR, "Unable to read to manifest '%s'\n", url); if (ret == 0) ret = AVERROR_INVALIDDATA; } else { LIBXML_TEST_VERSION - doc = xmlReadMemory(buf.str, filesize, c->base_url, NULL, 0); + doc = xmlReadMemory(buf.str, buf.len, c->base_url, NULL, 0); root_element = xmlDocGetRootElement(doc); node = root_element; From abc7d1c697e0dbe463ca6632e45142ae72d139a9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 9 Jan 2022 15:50:57 +0100 Subject: [PATCH 849/894] avformat/amr: Return error upon error Signed-off-by: Andreas Rheinhardt --- libavformat/amr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index 40d5bc9cc5..bc22c2f84f 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -91,7 +91,7 @@ static int amr_read_header(AVFormatContext *s) read = avio_read(pb, header, sizeof(header)); if (read < 0) - return ret; + return read; st = avformat_new_stream(s, NULL); if (!st) From c39b6e1425f041622a4e58d1c7c215c75a04a845 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Tue, 25 Feb 2020 10:02:33 +0800 Subject: [PATCH 850/894] lavc/qsvenc: add return check for ff_qsv_map_pixfmt Return an error directly if pixfmt is not supported for encoding, otherwise it may be hidden until query/check in MSDK. Signed-off-by: Linjie Fu Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 602436da63..4e7a15f060 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -578,7 +578,9 @@ static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) if (!desc) return AVERROR_BUG; - ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + ret = ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + if (ret < 0) + return AVERROR_BUG; q->param.mfx.FrameInfo.CropX = 0; q->param.mfx.FrameInfo.CropY = 0; @@ -681,7 +683,9 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) if (!desc) return AVERROR_BUG; - ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + ret = ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + if (ret < 0) + return AVERROR_BUG; q->param.mfx.FrameInfo.CropX = 0; q->param.mfx.FrameInfo.CropY = 0; From 479f3c65986fca0ccf56f4dadb5a5b167f466fc7 Mon Sep 17 00:00:00 2001 From: softworkz Date: Fri, 7 Jan 2022 07:01:31 +0000 Subject: [PATCH 851/894] avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11) Commit 8b83dad82512a6948b63408f964463b063ad24c9 introduced a regression in a way that scaling via vpp_qsv doesn't work any longer for devices with an MSDK runtime version lower than 1.19. This is true for older CPUs which are stuck at 1.11. The commit added checks for the compile-sdk version but it didn't test for the runtime version. Signed-off-by: softworkz Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 57 ++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index ab58a5777e..5c96703fd3 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -26,6 +26,7 @@ #include "libavutil/opt.h" #include "libavutil/eval.h" #include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" #include "libavutil/pixdesc.h" #include "libavutil/mathematics.h" @@ -139,8 +140,9 @@ static const AVOption options[] = { { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, +#ifdef QSV_HAVE_SCALING_CONFIG { "scale_mode", "scale mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" }, - +#endif { NULL } }; @@ -297,6 +299,32 @@ static int config_input(AVFilterLink *inlink) return 0; } +static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion *mfx_version) +{ + const AVFilterLink *inlink = ctx->inputs[0]; + AVBufferRef *device_ref; + AVHWDeviceContext *device_ctx; + AVQSVDeviceContext *device_hwctx; + + if (inlink->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + device_ref = frames_ctx->device_ref; + } else if (ctx->hw_device_ctx) { + device_ref = ctx->hw_device_ctx; + } else { + // Unavailable hw context doesn't matter in pass-through mode, + // so don't error here but let runtime version checks fail by setting to 0.0 + mfx_version->Major = 0; + mfx_version->Minor = 0; + return MFX_ERR_NONE; + } + + device_ctx = (AVHWDeviceContext *)device_ref->data; + device_hwctx = device_ctx->hwctx; + + return MFXQueryVersion(device_hwctx->session, mfx_version); +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -304,6 +332,7 @@ static int config_output(AVFilterLink *outlink) QSVVPPParam param = { NULL }; QSVVPPCrop crop = { 0 }; mfxExtBuffer *ext_buf[ENH_FILTERS_COUNT]; + mfxVersion mfx_version; AVFilterLink *inlink = ctx->inputs[0]; enum AVPixelFormat in_format; @@ -317,6 +346,11 @@ static int config_output(AVFilterLink *outlink) param.ext_buf = ext_buf; param.async_depth = vpp->async_depth; + if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n"); + return AVERROR(EINVAL); + } + if (inlink->format == AV_PIX_FMT_QSV) { if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) return AVERROR(EINVAL); @@ -467,19 +501,20 @@ static int config_output(AVFilterLink *outlink) #endif } - if (inlink->w != outlink->w || inlink->h != outlink->h) { #ifdef QSV_HAVE_SCALING_CONFIG - memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling)); - vpp->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; - vpp->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); - vpp->scale_conf.ScalingMode = vpp->scale_mode; + if (inlink->w != outlink->w || inlink->h != outlink->h) { + if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) { + memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling)); + vpp->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; + vpp->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); + vpp->scale_conf.ScalingMode = vpp->scale_mode; - param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf; -#else - av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is " - "not supported with this MSDK version.\n"); -#endif + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf; + } else + av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is " + "not supported with this MSDK version.\n"); } +#endif if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || From ecf09764dcfc4d90d2292d91f225bfd02211a17f Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 10 Jan 2022 08:29:17 +0100 Subject: [PATCH 852/894] lavfi/vf_libplacebo: fix side data stripping logic This was accidentally comparing s->colorspace against out->colorspace, which is wrong - the intent was to compare in->colorspace against out->colorspace. We also forgot to strip mastering metadata. Finally, the order is sort of wrong - we should strip this side data *before* process_frames, because otherwise it may end up being seen and used by libplacebo. Signed-off-by: Niklas Haas --- libavfilter/vf_libplacebo.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 1386aaeb3a..31ae28ac38 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -390,7 +390,7 @@ fail: static int filter_frame(AVFilterLink *link, AVFrame *in) { - int err, changed; + int err, changed_csp; AVFilterContext *ctx = link->dst; LibplaceboContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -426,22 +426,25 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) if (s->color_primaries >= 0) out->color_primaries = s->color_primaries; - RET(process_frames(ctx, out, in)); - - int changed_csp = s->colorspace != out->colorspace || - s->color_range != out->color_range || - s->color_trc != out->color_trc || - s->color_primaries != out->color_primaries; + changed_csp = in->colorspace != out->colorspace || + in->color_range != out->color_range || + in->color_trc != out->color_trc || + in->color_primaries != out->color_primaries; + /* Strip side data if no longer relevant */ + if (changed_csp) { + av_frame_remove_side_data(out, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); + av_frame_remove_side_data(out, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); + } if (s->apply_dovi || changed_csp) { - /* Strip side data if no longer relevant */ av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_RPU_BUFFER); av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_METADATA); } - if (s->apply_filmgrain) av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); + RET(process_frames(ctx, out, in)); + av_frame_free(&in); return ff_filter_frame(outlink, out); From f37e66b3937a914e16d89a9050f042ad89567245 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 10 Jan 2022 18:18:44 +0800 Subject: [PATCH 853/894] avformat/movenc: fix duration in mdhd box MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mvhd and tkhd present the post-editlist duration, while mdhd should have the pre-editlist duration. Regression since c2424b1f3. Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 2 +- tests/ref/fate/copy-trac3074 | 2 +- tests/ref/fate/mov-cover-image | 2 +- tests/ref/fate/mov-mp4-disposition-mpegts-remux | 2 +- tests/ref/fate/movenc | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index ab33371296..4c868919ae 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2960,7 +2960,7 @@ static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track) static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { - int64_t duration = calc_pts_duration(mov, track); + int64_t duration = calc_samples_pts_duration(mov, track); int version = duration < INT32_MAX ? 0 : 1; if (track->mode == MODE_ISM) diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074 index 4748296c2a..2ef7e702cd 100644 --- a/tests/ref/fate/copy-trac3074 +++ b/tests/ref/fate/copy-trac3074 @@ -1,4 +1,4 @@ -452d91e7c6889b787717fef25b6fce43 *tests/data/fate/copy-trac3074.mp4 +36fcc0a62695bcf93068fcfe68283ee9 *tests/data/fate/copy-trac3074.mp4 334016 tests/data/fate/copy-trac3074.mp4 #tb 0: 1/48000 #media_type 0: audio diff --git a/tests/ref/fate/mov-cover-image b/tests/ref/fate/mov-cover-image index 680d84e061..6141646afa 100644 --- a/tests/ref/fate/mov-cover-image +++ b/tests/ref/fate/mov-cover-image @@ -1,4 +1,4 @@ -4e92f776010bd7a727c11bf8c34cde1e *tests/data/fate/mov-cover-image.mp4 +54a8870d5d1e6cc4da28ae422aa70898 *tests/data/fate/mov-cover-image.mp4 1011919 tests/data/fate/mov-cover-image.mp4 #extradata 0: 2, 0x00340022 #tb 0: 1/44100 diff --git a/tests/ref/fate/mov-mp4-disposition-mpegts-remux b/tests/ref/fate/mov-mp4-disposition-mpegts-remux index 78f1668f65..184b952e04 100644 --- a/tests/ref/fate/mov-mp4-disposition-mpegts-remux +++ b/tests/ref/fate/mov-mp4-disposition-mpegts-remux @@ -1,4 +1,4 @@ -3c4432fe59ffd9f2ed6ba4b122cea935 *tests/data/fate/mov-mp4-disposition-mpegts-remux.mp4 +adb3b95c07a5f3e0c86641dd62f01dae *tests/data/fate/mov-mp4-disposition-mpegts-remux.mp4 5709 tests/data/fate/mov-mp4-disposition-mpegts-remux.mp4 #tb 0: 1/48000 #media_type 0: audio diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc index 81ea75f372..19e4e291b8 100644 --- a/tests/ref/fate/movenc +++ b/tests/ref/fate/movenc @@ -7,7 +7,7 @@ write_data len 36, time nopts, type header atom ftyp write_data len 2761, time nopts, type header atom - write_data len 908, time 966667, type sync atom moof write_data len 110, time nopts, type trailer atom - -caf0876986b5f033efc0958c338289cc 3815 non-empty-moov-elst +9d260d424e9de4626163fd25ccce5bab 3815 non-empty-moov-elst write_data len 36, time nopts, type header atom ftyp write_data len 2669, time nopts, type header atom - write_data len 908, time 1000000, type sync atom moof From 0b13c34a654891c91b9931fe59537dc028922f32 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 10 Jan 2022 15:41:50 +0100 Subject: [PATCH 854/894] avcodec/nvenc: zero-initialize NV_ENC_REGISTER_RESOURCE struct --- libavcodec/nvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 31dfed9241..850c46022b 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1856,7 +1856,7 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frame->hw_frames_ctx->data; - NV_ENC_REGISTER_RESOURCE reg; + NV_ENC_REGISTER_RESOURCE reg = { 0 }; int i, idx, ret; for (i = 0; i < ctx->nb_registered_frames; i++) { From 1b24a1ea14c028e4f98ea19098aec41334e9a7f0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Dec 2021 14:19:52 +0100 Subject: [PATCH 855/894] ffmpeg: remove a redundant assignment of interrupt_callback It is already set in open_output_file(). --- fftools/ffmpeg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index bdeff9a12e..5d134b025f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2951,8 +2951,6 @@ static int check_init_output_file(OutputFile *of, int file_index) return 0; } - of->ctx->interrupt_callback = int_cb; - ret = avformat_write_header(of->ctx, &of->opts); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, From 55ccbfd790410560a112a067cd205adf7a7fecd0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 29 Dec 2021 17:02:46 +0100 Subject: [PATCH 856/894] lavc/flac_parser: use a custom FIFO implementation FLAC parser currently uses AVFifoBuffer in a highly non-trivial manner, modifying its "internals" (the whole struct is currently public, but no other code touches its contents directly). E.g. it does not use any av_fifo functions for reading the FIFO contents, but implements its own. Reimplement the needed parts of the AVFifoBuffer API in the FLAC parser, making it completely self-contained. This will allow us to make AVFifoBuffer private. --- libavcodec/flac_parser.c | 198 +++++++++++++++++++++++++++++++-------- 1 file changed, 158 insertions(+), 40 deletions(-) diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index 3b27b152fc..cd9a2cb574 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -34,7 +34,6 @@ #include "libavutil/attributes.h" #include "libavutil/crc.h" -#include "libavutil/fifo.h" #include "bytestream.h" #include "parser.h" #include "flac.h" @@ -57,6 +56,14 @@ #define MAX_FRAME_HEADER_SIZE 16 #define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1) +typedef struct FifoBuffer { + uint8_t *buffer; + uint8_t *end; + uint8_t *rptr; + uint8_t *wptr; + int empty; +} FifoBuffer; + typedef struct FLACHeaderMarker { int offset; /**< byte offset from start of FLACParseContext->buffer */ int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores @@ -84,7 +91,7 @@ typedef struct FLACParseContext { int nb_headers_buffered; /**< number of headers that are buffered */ int best_header_valid; /**< flag set when the parser returns junk; if set return best_header next time */ - AVFifoBuffer *fifo_buf; /**< buffer to store all data until headers + FifoBuffer fifo_buf; /**< buffer to store all data until headers can be verified */ int end_padded; /**< specifies if fifo_buf's end is padded */ uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */ @@ -127,6 +134,18 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, return 1; } +static size_t flac_fifo_size(const FifoBuffer *f) +{ + if (f->wptr <= f->rptr && !f->empty) + return (f->wptr - f->buffer) + (f->end - f->rptr); + return f->wptr - f->rptr; +} + +static size_t flac_fifo_space(const FifoBuffer *f) +{ + return f->end - f->buffer - flac_fifo_size(f); +} + /** * Non-destructive fast fifo pointer fetching * Returns a pointer from the specified offset. @@ -143,7 +162,7 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, uint8_t **wrap_buf, int *allocated_size) { - AVFifoBuffer *f = fpc->fifo_buf; + FifoBuffer *f = &fpc->fifo_buf; uint8_t *start = f->rptr + offset; uint8_t *tmp_buf; @@ -180,9 +199,8 @@ static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, * A second call to flac_fifo_read (with new offset and len) should be called * to get the post-wrap buf if the returned len is less than the requested. **/ -static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len) +static uint8_t *flac_fifo_read(FifoBuffer *f, int offset, int *len) { - AVFifoBuffer *f = fpc->fifo_buf; uint8_t *start = f->rptr + offset; if (start >= f->end) @@ -191,6 +209,108 @@ static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len) return start; } +static int flac_fifo_grow(FifoBuffer *f, size_t inc) +{ + size_t size_old = f->end - f->buffer; + size_t offset_r = f->rptr - f->buffer; + size_t offset_w = f->wptr - f->buffer; + size_t size_new; + + uint8_t *tmp; + + if (size_old > SIZE_MAX - inc) + return AVERROR(EINVAL); + size_new = size_old + inc; + + tmp = av_realloc(f->buffer, size_new); + if (!tmp) + return AVERROR(ENOMEM); + + // move the data from the beginning of the ring buffer + // to the newly allocated space + if (offset_w <= offset_r && !f->empty) { + const size_t copy = FFMIN(inc, offset_w); + memcpy(tmp + size_old, tmp, copy); + if (copy < offset_w) { + memmove(tmp, tmp + copy, offset_w - copy); + offset_w -= copy; + } else + offset_w = size_old + copy; + } + + f->buffer = tmp; + f->end = f->buffer + size_new; + f->rptr = f->buffer + offset_r; + f->wptr = f->buffer + offset_w; + + return 0; +} + +static int flac_fifo_write(FifoBuffer *f, const uint8_t *src, size_t size) +{ + uint8_t *wptr; + + if (flac_fifo_space(f) < size) { + int ret = flac_fifo_grow(f, FFMAX(flac_fifo_size(f), size)); + if (ret < 0) + return ret; + } + + if (size) + f->empty = 0; + + wptr = f->wptr; + do { + size_t len = FFMIN(f->end - wptr, size); + memcpy(wptr, src, len); + src += len; + wptr += len; + if (wptr >= f->end) + wptr = f->buffer; + size -= len; + } while (size > 0); + + f->wptr = wptr; + + return 0; +} + +static void flac_fifo_drain(FifoBuffer *f, size_t size) +{ + size_t size_cur = flac_fifo_size(f); + + av_assert0(size_cur >= size); + if (size_cur == size) + f->empty = 1; + + f->rptr += size; + if (f->rptr >= f->end) + f->rptr -= f->end - f->buffer; +} + +static int flac_fifo_alloc(FifoBuffer *f, size_t size) +{ + memset(f, 0, sizeof(*f)); + + f->buffer = av_realloc(NULL, size); + if (!f->buffer) + return AVERROR(ENOMEM); + + f->wptr = f->buffer; + f->rptr = f->buffer; + f->end = f->buffer + size; + + f->empty = 1; + + return 0; +} + +static void flac_fifo_free(FifoBuffer *f) +{ + av_freep(&f->buffer); + memset(f, 0, sizeof(*f)); +} + static int find_headers_search_validate(FLACParseContext *fpc, int offset) { FLACFrameInfo fi; @@ -263,9 +383,9 @@ static int find_new_headers(FLACParseContext *fpc, int search_start) fpc->nb_headers_found = 0; /* Search for a new header of at most 16 bytes. */ - search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1); + search_end = flac_fifo_size(&fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1); read_len = search_end - search_start + 1; - buf = flac_fifo_read(fpc, search_start, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, search_start, &read_len); size = find_headers_search(fpc, buf, read_len, search_start); search_start += read_len - 1; @@ -277,7 +397,7 @@ static int find_new_headers(FLACParseContext *fpc, int search_start) /* search_start + 1 is the post-wrap offset in the fifo. */ read_len = search_end - (search_start + 1) + 1; - buf = flac_fifo_read(fpc, search_start + 1, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, search_start + 1, &read_len); wrap[1] = buf[0]; if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) { @@ -406,12 +526,12 @@ static int check_header_mismatch(FLACParseContext *fpc, } read_len = end->offset - start->offset; - buf = flac_fifo_read(fpc, start->offset, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, start->offset, &read_len); crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len); read_len = (end->offset - start->offset) - read_len; if (read_len) { - buf = flac_fifo_read(fpc, end->offset - read_len, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, end->offset - read_len, &read_len); crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len); } } @@ -500,7 +620,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, FLACHeaderMarker *header = fpc->best_header; FLACHeaderMarker *child = header->best_child; if (!child) { - *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset; + *poutbuf_size = flac_fifo_size(&fpc->fifo_buf) - header->offset; } else { *poutbuf_size = child->offset - header->offset; @@ -519,7 +639,6 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); - if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) { if (header->fi.is_var_size) fpc->pc->pts = header->fi.frame_or_sample_num; @@ -534,7 +653,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, /* Return the negative overread index so the client can compute pos. This should be the amount overread to the beginning of the child */ if (child) - return child->offset - av_fifo_size(fpc->fifo_buf); + return child->offset - flac_fifo_size(&fpc->fifo_buf); return 0; } @@ -586,7 +705,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, fpc->nb_headers_buffered--; } /* Release returned data from ring buffer. */ - av_fifo_drain(fpc->fifo_buf, best_child->offset); + flac_fifo_drain(&fpc->fifo_buf, best_child->offset); /* Fix the offset for the headers remaining to match the new buffer. */ for (curr = best_child->next; curr; curr = curr->next) @@ -620,7 +739,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, while ((buf_size && read_end < buf + buf_size && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) || (!buf_size && !fpc->end_padded)) { - int start_offset; + int start_offset, ret; /* Pad the end once if EOF, to check the final region for headers. */ if (!buf_size) { @@ -634,8 +753,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, nb_desired * FLAC_AVG_FRAME_SIZE); } - if (!av_fifo_space(fpc->fifo_buf) && - av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > + if (!flac_fifo_space(&fpc->fifo_buf) && + flac_fifo_size(&fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > fpc->nb_headers_buffered * 20) { /* There is less than one valid flac header buffered for 20 headers * buffered. Therefore the fifo is most likely filled with invalid @@ -644,24 +763,20 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, } /* Fill the buffer. */ - if ( av_fifo_space(fpc->fifo_buf) < read_end - read_start - && av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) { - av_log(avctx, AV_LOG_ERROR, - "couldn't reallocate buffer of size %"PTRDIFF_SPECIFIER"\n", - (read_end - read_start) + av_fifo_size(fpc->fifo_buf)); + if (buf_size) { + ret = flac_fifo_write(&fpc->fifo_buf, read_start, + read_end - read_start); + } else { + int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; + ret = flac_fifo_write(&fpc->fifo_buf, pad, sizeof(pad)); + } + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error buffering data\n"); goto handle_error; } - if (buf_size) { - av_fifo_generic_write(fpc->fifo_buf, (void*) read_start, - read_end - read_start, NULL); - } else { - int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; - av_fifo_generic_write(fpc->fifo_buf, pad, sizeof(pad), NULL); - } - /* Tag headers and update sequences. */ - start_offset = av_fifo_size(fpc->fifo_buf) - + start_offset = flac_fifo_size(&fpc->fifo_buf) - ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1)); start_offset = FFMAX(0, start_offset); nb_headers = find_new_headers(fpc, start_offset); @@ -689,14 +804,15 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, /* restore the state pre-padding */ if (fpc->end_padded) { - int warp = fpc->fifo_buf->wptr - fpc->fifo_buf->buffer < MAX_FRAME_HEADER_SIZE; + int empty = flac_fifo_size(&fpc->fifo_buf) == MAX_FRAME_HEADER_SIZE; + int warp = fpc->fifo_buf.wptr - fpc->fifo_buf.buffer < MAX_FRAME_HEADER_SIZE; /* HACK: drain the tail of the fifo */ - fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE; - fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE; + fpc->fifo_buf.wptr -= MAX_FRAME_HEADER_SIZE; if (warp) { - fpc->fifo_buf->wptr += fpc->fifo_buf->end - - fpc->fifo_buf->buffer; + fpc->fifo_buf.wptr += fpc->fifo_buf.end - + fpc->fifo_buf.buffer; } + fpc->fifo_buf.empty = empty; read_start = read_end = NULL; } } @@ -727,7 +843,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); return buf_size ? (read_end - buf) : (fpc->best_header->offset - - av_fifo_size(fpc->fifo_buf)); + flac_fifo_size(&fpc->fifo_buf)); } if (!buf_size) return get_best_header(fpc, poutbuf, poutbuf_size); @@ -742,11 +858,13 @@ handle_error: static av_cold int flac_parse_init(AVCodecParserContext *c) { FLACParseContext *fpc = c->priv_data; + int ret; + fpc->pc = c; /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before it drains. This is allocated early to avoid slow reallocation. */ - fpc->fifo_buf = av_fifo_alloc_array(FLAC_MIN_HEADERS + 3, FLAC_AVG_FRAME_SIZE); - if (!fpc->fifo_buf) { + ret = flac_fifo_alloc(&fpc->fifo_buf, (FLAC_MIN_HEADERS + 3) * FLAC_AVG_FRAME_SIZE); + if (ret < 0) { av_log(fpc->avctx, AV_LOG_ERROR, "couldn't allocate fifo_buf\n"); return AVERROR(ENOMEM); @@ -765,7 +883,7 @@ static void flac_parse_close(AVCodecParserContext *c) curr = temp; } fpc->headers = NULL; - av_fifo_freep(&fpc->fifo_buf); + flac_fifo_free(&fpc->fifo_buf); av_freep(&fpc->wrap_buf); } From d47dc0b0dfcc6010a57d4f2510c90b800ed40efc Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Dec 2021 12:57:48 +0100 Subject: [PATCH 857/894] lavf/dvenc: replace av_fifo_peek2() with av_fifo_generic_peek_at() This is the only remaining caller of av_fifo_peek2(), which will be deprecated. --- libavformat/dvenc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 9a853ba7ce..b76539b59f 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -201,8 +201,9 @@ static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr) if (of*2 >= size) continue; - frame_ptr[d] = *av_fifo_peek2(c->audio_data[channel], of*2+1); // FIXME: maybe we have to admit - frame_ptr[d+1] = *av_fifo_peek2(c->audio_data[channel], of*2); // that DV is a big-endian PCM + // FIXME: maybe we have to admit that DV is a big-endian PCM + av_fifo_generic_peek_at(c->audio_data[channel], frame_ptr + d, of * 2, 2, NULL); + FFSWAP(uint8_t, frame_ptr[d], frame_ptr[d + 1]); } frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ } From 63b013aa687662440c85ecff8fdc087123025bf6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Dec 2021 13:02:38 +0100 Subject: [PATCH 858/894] lavu/fifo: deprecate av_fifo_peek2() It returns a pointer inside the fifo's buffer, which cannot be safely used without accessing AVFifoBuffer internals. It is easier and safer to use av_fifo_generic_peek_at(). --- libavutil/fifo.h | 4 ++++ libavutil/tests/fifo.c | 8 -------- libavutil/version.h | 1 + tests/ref/fate/fifo | 26 -------------------------- 4 files changed, 5 insertions(+), 34 deletions(-) diff --git a/libavutil/fifo.h b/libavutil/fifo.h index dc7bc6f0dd..92b1cf50e4 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -156,6 +156,7 @@ int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space); */ void av_fifo_drain(AVFifoBuffer *f, int size); +#if FF_API_FIFO_PEEK2 /** * Return a pointer to the data stored in a FIFO buffer at a certain offset. * The FIFO buffer is not modified. @@ -165,7 +166,9 @@ void av_fifo_drain(AVFifoBuffer *f, int size); * than the used buffer size or the returned pointer will * point outside to the buffer data. * The used buffer size can be checked with av_fifo_size(). + * @deprecated use av_fifo_generic_peek_at() */ +attribute_deprecated static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) { uint8_t *ptr = f->rptr + offs; @@ -175,5 +178,6 @@ static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) ptr = f->end - (f->buffer - ptr); return ptr; } +#endif #endif /* AVUTIL_FIFO_H */ diff --git a/libavutil/tests/fifo.c b/libavutil/tests/fifo.c index 8a550e088b..a17d913233 100644 --- a/libavutil/tests/fifo.c +++ b/libavutil/tests/fifo.c @@ -30,14 +30,6 @@ int main(void) for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) av_fifo_generic_write(fifo, &i, sizeof(int), NULL); - /* peek at FIFO */ - n = av_fifo_size(fifo) / sizeof(int); - for (i = -n + 1; i < n; i++) { - int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int)); - printf("%d: %d\n", i, *v); - } - printf("\n"); - /* peek_at at FIFO */ n = av_fifo_size(fifo) / sizeof(int); for (i = 0; i < n; i++) { diff --git a/libavutil/version.h b/libavutil/version.h index 5f45cf9c53..953aac9d94 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -109,6 +109,7 @@ #define FF_API_DECLARE_ALIGNED (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_COLORSPACE_NAME (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_AV_MALLOCZ_ARRAY (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 58) /** * @} diff --git a/tests/ref/fate/fifo b/tests/ref/fate/fifo index 2b18ed5ffc..1b0e005412 100644 --- a/tests/ref/fate/fifo +++ b/tests/ref/fate/fifo @@ -1,29 +1,3 @@ --12: 1 --11: 2 --10: 3 --9: 4 --8: 5 --7: 6 --6: 7 --5: 8 --4: 9 --3: 10 --2: 11 --1: 12 -0: 0 -1: 1 -2: 2 -3: 3 -4: 4 -5: 5 -6: 6 -7: 7 -8: 8 -9: 9 -10: 10 -11: 11 -12: 12 - 0: 0 1: 1 2: 2 From 5010c481d1a4bbd52655c43f5d7627d4c0a90f72 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Dec 2021 13:44:06 +0100 Subject: [PATCH 859/894] lavu/fifo: simplify av_fifo_alloc() Turn it into a wrapper around av_fifo_alloc_array(). --- libavutil/fifo.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 1060aedf13..5eee18a8c8 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -24,9 +24,10 @@ #include "common.h" #include "fifo.h" -static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) +AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) { AVFifoBuffer *f; + void *buffer = av_malloc_array(nmemb, size); if (!buffer) return NULL; f = av_mallocz(sizeof(AVFifoBuffer)); @@ -35,21 +36,14 @@ static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) return NULL; } f->buffer = buffer; - f->end = f->buffer + size; + f->end = f->buffer + nmemb * size; av_fifo_reset(f); return f; } AVFifoBuffer *av_fifo_alloc(unsigned int size) { - void *buffer = av_malloc(size); - return fifo_alloc_common(buffer, size); -} - -AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) -{ - void *buffer = av_malloc_array(nmemb, size); - return fifo_alloc_common(buffer, nmemb * size); + return av_fifo_alloc_array(size, 1); } void av_fifo_free(AVFifoBuffer *f) From 549ccea54e61e2e35b01a288466476504df03fd8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Dec 2021 15:06:15 +0100 Subject: [PATCH 860/894] lavu/fifo: do not copy the whole fifo when reallocating av_realloc() the buffer and only move the part of the ring buffer that needs it. Also avoids allocating a temporary fifo. --- libavutil/fifo.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 5eee18a8c8..171c1aa9cd 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -27,7 +27,7 @@ AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) { AVFifoBuffer *f; - void *buffer = av_malloc_array(nmemb, size); + void *buffer = av_realloc_array(NULL, nmemb, size); if (!buffer) return NULL; f = av_mallocz(sizeof(AVFifoBuffer)); @@ -83,17 +83,31 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) unsigned int old_size = f->end - f->buffer; if (old_size < new_size) { - int len = av_fifo_size(f); - AVFifoBuffer *f2 = av_fifo_alloc(new_size); + size_t offset_r = f->rptr - f->buffer; + size_t offset_w = f->wptr - f->buffer; + uint8_t *tmp; - if (!f2) + tmp = av_realloc(f->buffer, new_size); + if (!tmp) return AVERROR(ENOMEM); - av_fifo_generic_read(f, f2->buffer, len, NULL); - f2->wptr += len; - f2->wndx += len; - av_free(f->buffer); - *f = *f2; - av_free(f2); + + // move the data from the beginning of the ring buffer + // to the newly allocated space + // the second condition distinguishes full vs empty fifo + if (offset_w <= offset_r && av_fifo_size(f)) { + const size_t copy = FFMIN(new_size - old_size, offset_w); + memcpy(tmp + old_size, tmp, copy); + if (copy < offset_w) { + memmove(tmp, tmp + copy , offset_w - copy); + offset_w -= copy; + } else + offset_w = old_size + copy; + } + + f->buffer = tmp; + f->end = f->buffer + new_size; + f->rptr = f->buffer + offset_r; + f->wptr = f->buffer + offset_w; } return 0; } From 53f513c60b460f3597c831e41e455c40a2862920 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Dec 2021 11:29:32 +0100 Subject: [PATCH 861/894] lavu/fifo: drop useless comments This object was never intended to be thread-safe, so these carry no useful information. --- libavutil/fifo.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 171c1aa9cd..f38e8ff089 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -144,7 +144,6 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, memcpy(wptr, src, len); src = (uint8_t *)src + len; } -// Write memory barrier needed for SMP here in theory wptr += len; if (wptr >= f->end) wptr = f->buffer; @@ -197,7 +196,6 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void *, void *, int)) { -// Read memory barrier needed for SMP here in theory uint8_t *rptr = f->rptr; do { @@ -208,7 +206,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, memcpy(dest, rptr, len); dest = (uint8_t *)dest + len; } -// memory barrier needed for SMP here in theory rptr += len; if (rptr >= f->end) rptr -= f->end - f->buffer; @@ -221,7 +218,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void *, void *, int)) { -// Read memory barrier needed for SMP here in theory do { int len = FFMIN(f->end - f->rptr, buf_size); if (func) @@ -230,7 +226,6 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, memcpy(dest, f->rptr, len); dest = (uint8_t *)dest + len; } -// memory barrier needed for SMP here in theory av_fifo_drain(f, len); buf_size -= len; } while (buf_size > 0); From f480c43dfa797c12154f9d2c1fb6365c0ab953a6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Dec 2021 11:41:11 +0100 Subject: [PATCH 862/894] lavu/fifo: return errors on trying to read/write too much Trying to write too much will currently overwrite previous data. Trying to read too much will either av_assert2() in av_fifo_drain() or return old data. Trying to peek too much will either av_assert2() in av_fifo_generic_peek_at() or return old data. Return an error code in all these cases, which is safer and more consistent. --- libavutil/fifo.c | 18 +++++++++++------- libavutil/fifo.h | 8 +++++++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libavutil/fifo.c b/libavutil/fifo.c index f38e8ff089..d741bdd395 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -134,6 +134,9 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, uint32_t wndx= f->wndx; uint8_t *wptr= f->wptr; + if (size > av_fifo_space(f)) + return AVERROR(ENOSPC); + do { int len = FFMIN(f->end - wptr, size); if (func) { @@ -159,13 +162,8 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz { uint8_t *rptr = f->rptr; - av_assert2(offset >= 0); - - /* - * *ndx are indexes modulo 2^32, they are intended to overflow, - * to handle *ndx greater than 4gb. - */ - av_assert2(buf_size + (unsigned)offset <= f->wndx - f->rndx); + if (offset < 0 || buf_size > av_fifo_size(f) - offset) + return AVERROR(EINVAL); if (offset >= f->end - rptr) rptr += offset - (f->end - f->buffer); @@ -198,6 +196,9 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, { uint8_t *rptr = f->rptr; + if (buf_size > av_fifo_size(f)) + return AVERROR(EINVAL); + do { int len = FFMIN(f->end - rptr, buf_size); if (func) @@ -218,6 +219,9 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void *, void *, int)) { + if (buf_size > av_fifo_size(f)) + return AVERROR(EINVAL); + do { int len = FFMIN(f->end - f->rptr, buf_size); if (func) diff --git a/libavutil/fifo.h b/libavutil/fifo.h index 92b1cf50e4..f4fd291e59 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -91,6 +91,8 @@ int av_fifo_space(const AVFifoBuffer *f); * @param buf_size number of bytes to read * @param func generic read function * @param dest data destination + * + * @return a non-negative number on success, a negative error code on failure */ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)); @@ -101,6 +103,8 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz * @param buf_size number of bytes to read * @param func generic read function * @param dest data destination + * + * @return a non-negative number on success, a negative error code on failure */ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); @@ -110,6 +114,8 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func) * @param buf_size number of bytes to read * @param func generic read function * @param dest data destination + * + * @return a non-negative number on success, a negative error code on failure */ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); @@ -124,7 +130,7 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func) * func must return the number of bytes written to dest_buf, or <= 0 to * indicate no more data available to write. * If func is NULL, src is interpreted as a simple byte array for source data. - * @return the number of bytes written to the FIFO + * @return the number of bytes written to the FIFO or a negative error code on failure */ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); From 6c4074e4234edacfb3f37184fd68771df3cb2b7f Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 10 Jan 2022 12:18:58 -0300 Subject: [PATCH 863/894] avcodec/libdav1d: explicitly set Dav1dSettings.apply_grain Don't depend on its default value being 1, as that could change anytime. Signed-off-by: James Almer --- libavcodec/libdav1d.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 8e45f533cb..29fa4f9c3d 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -230,8 +230,8 @@ static av_cold int libdav1d_init(AVCodecContext *c) s.frame_size_limit = c->max_pixels; if (dav1d->apply_grain >= 0) s.apply_grain = dav1d->apply_grain; - else if (c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) - s.apply_grain = 0; + else + s.apply_grain = !(c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN); s.all_layers = dav1d->all_layers; if (dav1d->operating_point >= 0) From bbf00916e45ac8754f208c0584834cb330a89da2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 18 Nov 2021 10:07:36 +0100 Subject: [PATCH 864/894] fftools/cmdutils: Fix undefined 1 << 31 Signed-off-by: Andreas Rheinhardt --- fftools/cmdutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 1444ea2f07..4b50e15eef 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1823,7 +1823,7 @@ int show_sample_fmts(void *optctx, const char *opt, const char *arg) int show_dispositions(void *optctx, const char *opt, const char *arg) { for (int i = 0; i < 32; i++) { - const char *str = av_disposition_to_string(1 << i); + const char *str = av_disposition_to_string(1U << i); if (str) printf("%s\n", str); } From 3c2b67446875f925909fa33d8ee14264e11c293d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 10 Jan 2022 17:41:02 +0100 Subject: [PATCH 865/894] lavf/udp: do not return an uninitialized value from udp_open() --- libavformat/udp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/udp.c b/libavformat/udp.c index b8b0e19609..180d96a988 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -739,8 +739,10 @@ static int udp_open(URLContext *h, const char *uri, int flags) /* XXX: fix av_url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { /* only accepts null hostname if input */ - if (!(flags & AVIO_FLAG_READ)) + if (!(flags & AVIO_FLAG_READ)) { + ret = AVERROR(EINVAL); goto fail; + } } else { if ((ret = ff_udp_set_remote_url(h, uri)) < 0) goto fail; @@ -750,8 +752,10 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->local_port = port; udp_fd = udp_socket_create(h, &my_addr, &len, s->localaddr); - if (udp_fd < 0) + if (udp_fd < 0) { + ret = AVERROR(EIO); goto fail; + } s->local_addr_storage=my_addr; //store for future multicast join From 4b053b8db18eb0610b62a2c40d0327ae53f2387c Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 7 Jan 2022 16:11:12 -0300 Subject: [PATCH 866/894] avcodec/av1dec: honor the requested skip_frame level This supports dropping non-intra, non-key, or all frames. Tested-by: nevcairiel Signed-off-by: James Almer --- libavcodec/av1dec.c | 70 ++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 09df2bf421..62d459cded 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -585,16 +585,19 @@ static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *s { int ret; - ret = ff_thread_ref_frame(&dst->tf, &src->tf); + ret = av_buffer_replace(&dst->header_ref, src->header_ref); if (ret < 0) return ret; - dst->header_ref = av_buffer_ref(src->header_ref); - if (!dst->header_ref) - goto fail; - dst->raw_frame_header = src->raw_frame_header; + if (!src->tf.f->buf[0]) + return 0; + + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + if (src->hwaccel_picture_private) { dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); if (!dst->hwaccel_priv_buf) @@ -800,12 +803,6 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f) return ret; } - f->header_ref = av_buffer_ref(s->header_ref); - if (!f->header_ref) - return AVERROR(ENOMEM); - - f->raw_frame_header = s->raw_frame_header; - if ((ret = ff_thread_get_buffer(avctx, &f->tf, AV_GET_BUFFER_FLAG_REF)) < 0) goto fail; @@ -945,8 +942,7 @@ static int update_reference_list(AVCodecContext *avctx) for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) { if (header->refresh_frame_flags & (1 << i)) { - if (s->ref[i].tf.f->buf[0]) - av1_frame_unref(avctx, &s->ref[i]); + av1_frame_unref(avctx, &s->ref[i]); if ((ret = av1_frame_ref(avctx, &s->ref[i], &s->cur_frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to update frame %d in reference list\n", i); @@ -962,8 +958,27 @@ static int get_current_frame(AVCodecContext *avctx) AV1DecContext *s = avctx->priv_data; int ret; - if (s->cur_frame.tf.f->buf[0]) - av1_frame_unref(avctx, &s->cur_frame); + av1_frame_unref(avctx, &s->cur_frame); + + s->cur_frame.header_ref = av_buffer_ref(s->header_ref); + if (!s->cur_frame.header_ref) + return AVERROR(ENOMEM); + + s->cur_frame.raw_frame_header = s->raw_frame_header; + + ret = init_tile_data(s); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to init tile data.\n"); + return ret; + } + + if ((avctx->skip_frame >= AVDISCARD_NONINTRA && + (s->raw_frame_header->frame_type != AV1_FRAME_KEY && + s->raw_frame_header->frame_type != AV1_FRAME_INTRA_ONLY)) || + (avctx->skip_frame >= AVDISCARD_NONKEY && + s->raw_frame_header->frame_type != AV1_FRAME_KEY) || + avctx->skip_frame >= AVDISCARD_ALL) + return 0; ret = av1_frame_alloc(avctx, &s->cur_frame); if (ret < 0) { @@ -972,12 +987,6 @@ static int get_current_frame(AVCodecContext *avctx) return ret; } - ret = init_tile_data(s); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to init tile data.\n"); - return ret; - } - global_motion_params(s); skip_mode_params(s); coded_lossless_param(s); @@ -1077,8 +1086,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, s->raw_frame_header = &obu->obu.frame_header; if (s->raw_frame_header->show_existing_frame) { - if (s->cur_frame.tf.f->buf[0]) - av1_frame_unref(avctx, &s->cur_frame); + av1_frame_unref(avctx, &s->cur_frame); ret = av1_frame_ref(avctx, &s->cur_frame, &s->ref[s->raw_frame_header->frame_to_show_map_idx]); @@ -1093,9 +1101,11 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, goto end; } - ret = set_output_frame(avctx, frame, pkt, got_frame); - if (ret < 0) - av_log(avctx, AV_LOG_ERROR, "Set output frame error.\n"); + if (s->cur_frame.tf.f->buf[0]) { + ret = set_output_frame(avctx, frame, pkt, got_frame); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "Set output frame error.\n"); + } s->raw_frame_header = NULL; @@ -1111,7 +1121,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, s->cur_frame.spatial_id = header->spatial_id; s->cur_frame.temporal_id = header->temporal_id; - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.tf.f->buf[0]) { ret = avctx->hwaccel->start_frame(avctx, unit->data, unit->data_size); if (ret < 0) { @@ -1138,7 +1148,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, if (ret < 0) goto end; - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.tf.f->buf[0]) { ret = avctx->hwaccel->decode_slice(avctx, raw_tile_group->tile_data.data, raw_tile_group->tile_data.data_size); @@ -1161,7 +1171,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, } if (raw_tile_group && (s->tile_num == raw_tile_group->tg_end + 1)) { - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.tf.f->buf[0]) { ret = avctx->hwaccel->end_frame(avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "HW accel end frame fail.\n"); @@ -1175,7 +1185,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, goto end; } - if (s->raw_frame_header->show_frame) { + if (s->raw_frame_header->show_frame && s->cur_frame.tf.f->buf[0]) { ret = set_output_frame(avctx, frame, pkt, got_frame); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Set output frame error\n"); From 9e445a5be2dca30a1f1103c73440648ccf5af9b1 Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Wed, 24 Nov 2021 13:15:20 -0800 Subject: [PATCH 867/894] swscale/x86/output.asm: add x86-optimized planer gbr yuv2anyX functions changes since v2: * fixed label changes since v1: * remove vex intruction on sse4 path * some load/pack marcos use less intructions * fixed some typos yuv2gbrp_full_X_4_512_c: 12757.6 yuv2gbrp_full_X_4_512_sse2: 8946.6 yuv2gbrp_full_X_4_512_sse4: 5138.6 yuv2gbrp_full_X_4_512_avx2: 3889.6 yuv2gbrap_full_X_4_512_c: 15368.6 yuv2gbrap_full_X_4_512_sse2: 11916.1 yuv2gbrap_full_X_4_512_sse4: 6294.6 yuv2gbrap_full_X_4_512_avx2: 3477.1 yuv2gbrp9be_full_X_4_512_c: 14381.6 yuv2gbrp9be_full_X_4_512_sse2: 9139.1 yuv2gbrp9be_full_X_4_512_sse4: 5150.1 yuv2gbrp9be_full_X_4_512_avx2: 2834.6 yuv2gbrp9le_full_X_4_512_c: 12990.1 yuv2gbrp9le_full_X_4_512_sse2: 9118.1 yuv2gbrp9le_full_X_4_512_sse4: 5132.1 yuv2gbrp9le_full_X_4_512_avx2: 2833.1 yuv2gbrp10be_full_X_4_512_c: 14401.6 yuv2gbrp10be_full_X_4_512_sse2: 9133.1 yuv2gbrp10be_full_X_4_512_sse4: 5126.1 yuv2gbrp10be_full_X_4_512_avx2: 2837.6 yuv2gbrp10le_full_X_4_512_c: 12718.1 yuv2gbrp10le_full_X_4_512_sse2: 9106.1 yuv2gbrp10le_full_X_4_512_sse4: 5120.1 yuv2gbrp10le_full_X_4_512_avx2: 2826.1 yuv2gbrap10be_full_X_4_512_c: 18535.6 yuv2gbrap10be_full_X_4_512_sse2: 33617.6 yuv2gbrap10be_full_X_4_512_sse4: 6264.1 yuv2gbrap10be_full_X_4_512_avx2: 3422.1 yuv2gbrap10le_full_X_4_512_c: 16724.1 yuv2gbrap10le_full_X_4_512_sse2: 11787.1 yuv2gbrap10le_full_X_4_512_sse4: 6282.1 yuv2gbrap10le_full_X_4_512_avx2: 3441.6 yuv2gbrp12be_full_X_4_512_c: 13723.6 yuv2gbrp12be_full_X_4_512_sse2: 9128.1 yuv2gbrp12be_full_X_4_512_sse4: 7997.6 yuv2gbrp12be_full_X_4_512_avx2: 2844.1 yuv2gbrp12le_full_X_4_512_c: 12257.1 yuv2gbrp12le_full_X_4_512_sse2: 9107.6 yuv2gbrp12le_full_X_4_512_sse4: 5142.6 yuv2gbrp12le_full_X_4_512_avx2: 2837.6 yuv2gbrap12be_full_X_4_512_c: 18511.1 yuv2gbrap12be_full_X_4_512_sse2: 12156.6 yuv2gbrap12be_full_X_4_512_sse4: 6251.1 yuv2gbrap12be_full_X_4_512_avx2: 3444.6 yuv2gbrap12le_full_X_4_512_c: 16687.1 yuv2gbrap12le_full_X_4_512_sse2: 11785.1 yuv2gbrap12le_full_X_4_512_sse4: 6243.6 yuv2gbrap12le_full_X_4_512_avx2: 3446.1 yuv2gbrp14be_full_X_4_512_c: 13690.6 yuv2gbrp14be_full_X_4_512_sse2: 9120.6 yuv2gbrp14be_full_X_4_512_sse4: 5138.1 yuv2gbrp14be_full_X_4_512_avx2: 2843.1 yuv2gbrp14le_full_X_4_512_c: 14995.6 yuv2gbrp14le_full_X_4_512_sse2: 9119.1 yuv2gbrp14le_full_X_4_512_sse4: 5126.1 yuv2gbrp14le_full_X_4_512_avx2: 2843.1 yuv2gbrp16be_full_X_4_512_c: 12367.1 yuv2gbrp16be_full_X_4_512_sse2: 8233.6 yuv2gbrp16be_full_X_4_512_sse4: 4820.1 yuv2gbrp16be_full_X_4_512_avx2: 2666.6 yuv2gbrp16le_full_X_4_512_c: 10904.1 yuv2gbrp16le_full_X_4_512_sse2: 8214.1 yuv2gbrp16le_full_X_4_512_sse4: 4824.1 yuv2gbrp16le_full_X_4_512_avx2: 2629.1 yuv2gbrap16be_full_X_4_512_c: 26569.6 yuv2gbrap16be_full_X_4_512_sse2: 10884.1 yuv2gbrap16be_full_X_4_512_sse4: 5488.1 yuv2gbrap16be_full_X_4_512_avx2: 3272.1 yuv2gbrap16le_full_X_4_512_c: 14010.1 yuv2gbrap16le_full_X_4_512_sse2: 10562.1 yuv2gbrap16le_full_X_4_512_sse4: 5463.6 yuv2gbrap16le_full_X_4_512_avx2: 3255.1 yuv2gbrpf32be_full_X_4_512_c: 14524.1 yuv2gbrpf32be_full_X_4_512_sse2: 8552.6 yuv2gbrpf32be_full_X_4_512_sse4: 4636.1 yuv2gbrpf32be_full_X_4_512_avx2: 2474.6 yuv2gbrpf32le_full_X_4_512_c: 13060.6 yuv2gbrpf32le_full_X_4_512_sse2: 9682.6 yuv2gbrpf32le_full_X_4_512_sse4: 4298.1 yuv2gbrpf32le_full_X_4_512_avx2: 2453.1 yuv2gbrapf32be_full_X_4_512_c: 18629.6 yuv2gbrapf32be_full_X_4_512_sse2: 11363.1 yuv2gbrapf32be_full_X_4_512_sse4: 15201.6 yuv2gbrapf32be_full_X_4_512_avx2: 3727.1 yuv2gbrapf32le_full_X_4_512_c: 16677.6 yuv2gbrapf32le_full_X_4_512_sse2: 10221.6 yuv2gbrapf32le_full_X_4_512_sse4: 5693.6 yuv2gbrapf32le_full_X_4_512_avx2: 3656.6 Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libswscale/x86/output.asm | 434 +++++++++++++++++++++++++++++++++++++- libswscale/x86/swscale.c | 98 +++++++++ tests/checkasm/Makefile | 2 +- tests/checkasm/checkasm.c | 1 + tests/checkasm/checkasm.h | 1 + tests/checkasm/sw_gbrp.c | 198 +++++++++++++++++ tests/fate/checkasm.mak | 1 + 7 files changed, 733 insertions(+), 2 deletions(-) create mode 100644 tests/checkasm/sw_gbrp.c diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm index 52cf9f2c2e..1e498fddf6 100644 --- a/libswscale/x86/output.asm +++ b/libswscale/x86/output.asm @@ -38,7 +38,49 @@ pw_32: times 8 dw 32 pd_255: times 8 dd 255 pw_512: times 8 dw 512 pw_1024: times 8 dw 1024 - +pd_65535_invf: times 8 dd 0x37800080 ;1.0/65535.0 +pd_yuv2gbrp16_start: times 8 dd -0x40000000 +pd_yuv2gbrp_y_start: times 8 dd (1 << 9) +pd_yuv2gbrp_uv_start: times 8 dd ((1 << 9) - (128 << 19)) +pd_yuv2gbrp_a_start: times 8 dd (1 << 18) +pd_yuv2gbrp16_offset: times 8 dd 0x10000 ;(1 << 16) +pd_yuv2gbrp16_round13: times 8 dd 0x02000 ;(1 << 13) +pd_yuv2gbrp16_a_offset: times 8 dd 0x20002000 +pd_yuv2gbrp16_upper30: times 8 dd 0x3FFFFFFF ;(1<<30) - 1 +pd_yuv2gbrp16_upper27: times 8 dd 0x07FFFFFF ;(1<<27) - 1 +pd_yuv2gbrp16_upperC: times 8 dd 0xC0000000 +pb_pack_shuffle8: db 0, 4, 8, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 0, 4, 8, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1 +pb_pack_shuffle16le: db 0, 1, 4, 5, \ + 8, 9, 12, 13, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 0, 1, 4, 5, \ + 8, 9, 12, 13 +pb_pack_shuffle16be: db 1, 0, 5, 4, \ + 9, 8, 13, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 1, 0, 5, 4, \ + 9, 8, 13, 12 +pb_shuffle32be: db 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12, \ + 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12 yuv2nv12_shuffle_mask: times 2 db 0, 4, 8, 12, \ -1, -1, -1, -1, \ -1, -1, -1, -1, \ @@ -549,3 +591,393 @@ yuv2nv12cX_fn yuv2nv12 yuv2nv12cX_fn yuv2nv21 %endif %endif ; ARCH_X86_64 + +;----------------------------------------------------------------------------- +; planar grb yuv2anyX functions +; void ff_yuv2_full_X_(SwsContext *c, const int16_t *lumFilter, +; const int16_t **lumSrcx, int lumFilterSize, +; const int16_t *chrFilter, const int16_t **chrUSrcx, +; const int16_t **chrVSrcx, int chrFilterSize, +; const int16_t **alpSrcx, uint8_t **dest, +; int dstW, int y) +;----------------------------------------------------------------------------- + +%if ARCH_X86_64 +struc SwsContext + .padding: resb 40292 ; offsetof(SwsContext, yuv2rgb_y_offset) + .yuv2rgb_y_offset: resd 1 + .yuv2rgb_y_coeff: resd 1 + .yuv2rgb_v2r_coeff: resd 1 + .yuv2rgb_v2g_coeff: resd 1 + .yuv2rgb_u2g_coeff: resd 1 + .yuv2rgb_u2b_coeff: resd 1 +endstruc + +%define R m0 +%define G m1 +%define B m2 +%define A m3 + +%define Y m4 +%define U m5 +%define V m6 + +; Clip a signed integer to an unsigned power of two range. +; av_clip_uintp2 +; 1 - dest +; 2 - bit position to clip at +%macro CLIPP2 2 + ; (~a) >> 31 & ((1<= 16 + movu m%1, [ptrq + xq*4] +%else + LOAD16 %1, [ptrq + xq*2] +%endif +%endmacro + +; 1 - dest +; 2 - source +%macro STORE8 2 + mov ptrq, %1 + %if mmsize > 16 + pshufb m%2, [pb_pack_shuffle8] + vextractf128 xm4, m%2, 1 + por xm%2, xm4 + movq [ptrq + xq], xm%2 + %else + %if cpuflag(sse4) + pshufb m%2, [pb_pack_shuffle8] + %else + psrldq m4, m%2, 3 + por m%2, m4 + psrldq m4, m%2, 6 + por m%2, m4 + %endif + movd [ptrq + xq], m%2 + %endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - is big endian +%macro STORE16 3 + mov ptrq, %1 + %if mmsize > 16 + %if %3 ; bigendian + pshufb m%2, [pb_pack_shuffle16be] + %else + pshufb m%2, [pb_pack_shuffle16le] + %endif + vpermq m%2, m%2, (3 << 6 | 0 << 4 | 3 << 2 | 0 << 0) + movu [ptrq + xq*2], xm%2 + %else + %if cpuflag(sse4) && %3 ; bigendian + pshufb m%2, [pb_pack_shuffle16be] + %elif cpuflag(sse4) + pshufb m%2, [pb_pack_shuffle16le] + %else + pshuflw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufhw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m%2, m%2, (3 << 6 | 3 << 4 | 2 << 2 | 0 << 0) + %if %3 ; bigendian + psrlw m4, m%2, 8 + psllw m%2, 8 + por m%2, m4 + %endif + %endif + movq [ptrq + xq*2], m%2 + %endif +%endmacro + +%macro SWAP32 1 +%if mmsize > 16 || cpuflag(sse4) + pshufb m%1, [pb_shuffle32be] +%else + psrlw m4, m%1, 8 + psllw m%1, 8 + por m%1, m4 + pshuflw m%1, m%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) + pshufhw m%1, m%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) +%endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - depth +; 4 - is big endian +%macro STORE_PIXELS 4 +%if %3 > 16 + %if %4 + SWAP32 %2 + %endif + mov ptrq, %1 + movu [ptrq + xq*4], m%2 +%elif %3 > 8 + STORE16 %1, %2, %4 +%else + STORE8 %1, %2 +%endif +%endmacro + +%macro PMULLO 3 +%if cpuflag(sse4) || mmsize > 16 + pmulld %1, %2, %3 +%else + %ifidni %1, %2 + %else + mova %1, %2 + %endif + pshufd m7, %1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) ; 0xb1 + pshufd m8, %3, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) ; 0xb1 + pmuludq m7, m8 + pshufd m7, m7, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) ; 0xd8 + pmuludq %1, %3 + pshufd %1, %1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) ; 0xd8 + punpckldq %1, m7 +%endif +%endmacro + +; 1 - name +; 2 - depth +; 3 - has alpha +; 3 - is big endian +; 5 - is float +%macro yuv2gbrp_fn 5 +%define DEPTH %2 +%define HAS_ALPHA %3 +%define IS_BE %4 +%define FLOAT %5 +%define SH (22 + 8 - DEPTH) + +%if DEPTH >= 16 + %define RGB_SHIFT 14 + %define A_SHIFT 14 +%elif 22 != SH + %define RGB_SHIFT SH + %define A_SHIFT (SH-3) +%else + %define RGB_SHIFT 22 + %define A_SHIFT 19 +%endif + +%if DEPTH >= 16 + %define YUV_SHIFT 14 + %define Y_START m9 + %define Y_ROUND [pd_yuv2gbrp16_round13] + %define UV_START m9 + %define A_START m9 + %define A_CLIP2P 30 +%else + %define YUV_SHIFT 10 + %define Y_START [pd_yuv2gbrp_y_start] + %define Y_ROUND m9 + %define UV_START [pd_yuv2gbrp_uv_start] + %define A_START [pd_yuv2gbrp_a_start] + %define A_CLIP2P 27 +%endif + +cglobal yuv2%1_full_X, 12, 14, 16, ptr, lumFilter, lumSrcx, lumFilterSize, chrFilter, chrUSrcx, chrVSrcx, chrFilterSize, alpSrcx, dest, dstW, y, x, j + VBROADCASTSS m10, dword [ptrq + SwsContext.yuv2rgb_y_offset] + VBROADCASTSS m11, dword [ptrq + SwsContext.yuv2rgb_y_coeff] + VBROADCASTSS m12, dword [ptrq + SwsContext.yuv2rgb_v2r_coeff] + VBROADCASTSS m13, dword [ptrq + SwsContext.yuv2rgb_v2g_coeff] + VBROADCASTSS m14, dword [ptrq + SwsContext.yuv2rgb_u2g_coeff] + VBROADCASTSS m15, dword [ptrq + SwsContext.yuv2rgb_u2b_coeff] + +%if DEPTH >= 16 + movu m9, [pd_yuv2gbrp16_start] +%else + mov xq, (1 << (SH-1)) + movq xm9, xq + VBROADCASTSS m9, xm9 +%endif + xor xq, xq + + %%loop_x: + movu Y, Y_START + movu U, UV_START + movu V, UV_START + + xor jq, jq + %%loop_luma: + movsx ptrd, word [lumFilterq + jq*2] + movd xm0, ptrd + VBROADCASTSS m0, xm0 + LOAD_PIXELS 1, lumSrcxq, DEPTH + PMULLO m1, m1, m0 + paddd Y, m1 + inc jd + cmp jd, lumFilterSized + jl %%loop_luma + +%if HAS_ALPHA + cmp alpSrcxq, 0 + je %%skip_alpha_load + xor jq, jq + movu A, A_START + %%loop_alpha: + movsx ptrd, word [lumFilterq + jq*2] + movd xm0, ptrd + VBROADCASTSS m0, xm0 + LOAD_PIXELS 1, alpSrcxq, DEPTH + PMULLO m1, m1, m0 + paddd A, m1 + inc jd + cmp jd, lumFilterSized + jl %%loop_alpha +%if DEPTH >= 16 + psrad A, 1 + paddd A, [pd_yuv2gbrp16_a_offset] +%endif + %%skip_alpha_load: +%endif + xor jq, jq + %%loop_chr: + movsx ptrd, word [chrFilterq + jq*2] + movd xm0, ptrd + VBROADCASTSS m0, xm0 + LOAD_PIXELS 1, chrUSrcxq, DEPTH + LOAD_PIXELS 2, chrVSrcxq, DEPTH + PMULLO m1, m1, m0 + PMULLO m2, m2, m0 + paddd U, m1 + paddd V, m2 + inc jd + cmp jd, chrFilterSized + jl %%loop_chr + + psrad Y, YUV_SHIFT +%if DEPTH >= 16 + paddd Y, [pd_yuv2gbrp16_offset] +%endif + psrad U, YUV_SHIFT + psrad V, YUV_SHIFT + + psubd Y, m10 ; yuv2rgb_y_offset + PMULLO Y, Y, m11 ; yuv2rgb_y_coeff + paddd Y, Y_ROUND + + PMULLO R, V, m12 ; yuv2rgb_v2r_coeff + PMULLO B, U, m15 ; yuv2rgb_u2b_coeff + + PMULLO U, U, m14 ; yuv2rgb_u2g_coeff + PMULLO V, V, m13 ; yuv2rgb_v2g_coeff + paddd G, U, V + paddd R, Y + paddd G, Y + paddd B, Y + + CLIPP2 R, 30 + CLIPP2 G, 30 + CLIPP2 B, 30 + + psrad R, RGB_SHIFT + psrad G, RGB_SHIFT + psrad B, RGB_SHIFT + +%if FLOAT + cvtdq2ps R, R + cvtdq2ps G, G + cvtdq2ps B, B + mulps R, [pd_65535_invf] + mulps G, [pd_65535_invf] + mulps B, [pd_65535_invf] +%endif + STORE_PIXELS [destq + 0], 1, DEPTH, IS_BE ; G + STORE_PIXELS [destq + 8], 2, DEPTH, IS_BE ; B + STORE_PIXELS [destq + 16], 0, DEPTH, IS_BE ; R + +%if HAS_ALPHA + cmp alpSrcxq, 0 + je %%skip_alpha_store + CLIPP2 A, A_CLIP2P + psrad A, A_SHIFT +%if FLOAT + cvtdq2ps A, A + mulps A, [pd_65535_invf] +%endif + STORE_PIXELS [destq + 24], 3, DEPTH, IS_BE + %%skip_alpha_store: +%endif + add xq, mmsize/4 + cmp xd, dstWd + jl %%loop_x + + RET +%endmacro + +%macro yuv2gbrp_fn_decl 2 +INIT_%1 %2 +yuv2gbrp_fn gbrp, 8, 0, 0, 0 +yuv2gbrp_fn gbrap, 8, 1, 0, 0 +yuv2gbrp_fn gbrp9le, 9, 0, 0, 0 +yuv2gbrp_fn gbrp10le, 10, 0, 0, 0 +yuv2gbrp_fn gbrap10le, 10, 1, 0, 0 +yuv2gbrp_fn gbrp12le, 12, 0, 0, 0 +yuv2gbrp_fn gbrap12le, 12, 1, 0, 0 +yuv2gbrp_fn gbrp14le, 14, 0, 0, 0 +yuv2gbrp_fn gbrp16le, 16, 0, 0, 0 +yuv2gbrp_fn gbrap16le, 16, 1, 0, 0 +yuv2gbrp_fn gbrpf32le, 32, 0, 0, 1 +yuv2gbrp_fn gbrapf32le, 32, 1, 0, 1 + +yuv2gbrp_fn gbrp9be, 9, 0, 1, 0 +yuv2gbrp_fn gbrp10be, 10, 0, 1, 0 +yuv2gbrp_fn gbrap10be, 10, 1, 1, 0 +yuv2gbrp_fn gbrp12be, 12, 0, 1, 0 +yuv2gbrp_fn gbrap12be, 12, 1, 1, 0 +yuv2gbrp_fn gbrp14be, 14, 0, 1, 0 +yuv2gbrp_fn gbrp16be, 16, 0, 1, 0 +yuv2gbrp_fn gbrap16be, 16, 1, 1, 0 +yuv2gbrp_fn gbrpf32be, 32, 0, 1, 1 +yuv2gbrp_fn gbrapf32be, 32, 1, 1, 1 +%endmacro + +yuv2gbrp_fn_decl XMM, sse2 +yuv2gbrp_fn_decl XMM, sse4 + +%if HAVE_AVX2_EXTERNAL +yuv2gbrp_fn_decl YMM, avx2 +%endif + +%endif ; ARCH_X86_64 diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index fdc93866a6..d5a467da0e 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -353,6 +353,43 @@ void ff_yuv2 ## fmt ## cX_ ## opt(enum AVPixelFormat format, const uint8_t *dith YUV2NV_DECL(nv12, avx2); YUV2NV_DECL(nv21, avx2); + +#define YUV2GBRP_FN_DECL(fmt, opt) \ +void ff_yuv2##fmt##_full_X_ ##opt(SwsContext *c, const int16_t *lumFilter, \ + const int16_t **lumSrcx, int lumFilterSize, \ + const int16_t *chrFilter, const int16_t **chrUSrcx, \ + const int16_t **chrVSrcx, int chrFilterSize, \ + const int16_t **alpSrcx, uint8_t **dest, \ + int dstW, int y) + +#define YUV2GBRP_DECL(opt) \ +YUV2GBRP_FN_DECL(gbrp, opt); \ +YUV2GBRP_FN_DECL(gbrap, opt); \ +YUV2GBRP_FN_DECL(gbrp9le, opt); \ +YUV2GBRP_FN_DECL(gbrp10le, opt); \ +YUV2GBRP_FN_DECL(gbrap10le, opt); \ +YUV2GBRP_FN_DECL(gbrp12le, opt); \ +YUV2GBRP_FN_DECL(gbrap12le, opt); \ +YUV2GBRP_FN_DECL(gbrp14le, opt); \ +YUV2GBRP_FN_DECL(gbrp16le, opt); \ +YUV2GBRP_FN_DECL(gbrap16le, opt); \ +YUV2GBRP_FN_DECL(gbrpf32le, opt); \ +YUV2GBRP_FN_DECL(gbrapf32le, opt); \ +YUV2GBRP_FN_DECL(gbrp9be, opt); \ +YUV2GBRP_FN_DECL(gbrp10be, opt); \ +YUV2GBRP_FN_DECL(gbrap10be, opt); \ +YUV2GBRP_FN_DECL(gbrp12be, opt); \ +YUV2GBRP_FN_DECL(gbrap12be, opt); \ +YUV2GBRP_FN_DECL(gbrp14be, opt); \ +YUV2GBRP_FN_DECL(gbrp16be, opt); \ +YUV2GBRP_FN_DECL(gbrap16be, opt); \ +YUV2GBRP_FN_DECL(gbrpf32be, opt); \ +YUV2GBRP_FN_DECL(gbrapf32be, opt); + +YUV2GBRP_DECL(sse2); +YUV2GBRP_DECL(sse4); +YUV2GBRP_DECL(avx2); + #endif av_cold void ff_sws_init_swscale_x86(SwsContext *c) @@ -601,5 +638,66 @@ switch(c->dstBpc){ \ break; } } + + if(c->flags & SWS_FULL_CHR_H_INT) { + + /* yuv2gbrp uses the SwsContext for yuv coefficients + if struct offsets change the asm needs to be updated too */ + av_assert0(offsetof(SwsContext, yuv2rgb_y_offset) == 40292); + +#define YUV2ANYX_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->yuv2anyX = ff_yuv2##name##_full_X_##opt; \ + break; + +#define YUV2ANYX_GBRAP_CASES(opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP, gbrp, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP, gbrap, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP9LE, gbrp9le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP10LE, gbrp10le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP10LE, gbrap10le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP12LE, gbrp12le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP12LE, gbrap12le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP14LE, gbrp14le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP16LE, gbrp16le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP16LE, gbrap16le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRPF32LE, gbrpf32le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAPF32LE, gbrapf32le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP9BE, gbrp9be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP10BE, gbrp10be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP10BE, gbrap10be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP12BE, gbrp12be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP12BE, gbrap12be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP14BE, gbrp14be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP16BE, gbrp16be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP16BE, gbrap16be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRPF32BE, gbrpf32be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAPF32BE, gbrapf32be, opt) + + if (EXTERNAL_SSE2(cpu_flags)) { + switch (c->dstFormat) { + YUV2ANYX_GBRAP_CASES(sse2) + default: + break; + } + } + + if (EXTERNAL_SSE4(cpu_flags)) { + switch (c->dstFormat) { + YUV2ANYX_GBRAP_CASES(sse4) + default: + break; + } + } + + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + switch (c->dstFormat) { + YUV2ANYX_GBRAP_CASES(avx2) + default: + break; + } + } + } + #endif } diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 4ef5fa87da..f768b1144e 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -45,7 +45,7 @@ AVFILTEROBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) # swscale tests -SWSCALEOBJS += sw_rgb.o sw_scale.o +SWSCALEOBJS += sw_gbrp.o sw_rgb.o sw_scale.o CHECKASMOBJS-$(CONFIG_SWSCALE) += $(SWSCALEOBJS) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 90d080de02..f74125e810 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -183,6 +183,7 @@ static const struct { #endif #endif #if CONFIG_SWSCALE + { "sw_gbrp", checkasm_check_sw_gbrp }, { "sw_rgb", checkasm_check_sw_rgb }, { "sw_scale", checkasm_check_sw_scale }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 68b0697d3e..c3192d8c23 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -72,6 +72,7 @@ void checkasm_check_opusdsp(void); void checkasm_check_pixblockdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); +void checkasm_check_sw_gbrp(void); void checkasm_check_sw_rgb(void); void checkasm_check_sw_scale(void); void checkasm_check_utvideodsp(void); diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c new file mode 100644 index 0000000000..61b2b9d6a1 --- /dev/null +++ b/tests/checkasm/sw_gbrp.c @@ -0,0 +1,198 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" +#include "libavutil/pixdesc.h" + +#include "libswscale/swscale.h" +#include "libswscale/swscale_internal.h" + +#include "checkasm.h" + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + for (j = 0; j < size; j+=4) \ + AV_WN32(buf + j, rnd()); \ + } while (0) + +static const int planar_fmts[] = { + AV_PIX_FMT_GBRP, + AV_PIX_FMT_GBRP9BE, + AV_PIX_FMT_GBRP9LE, + AV_PIX_FMT_GBRP10BE, + AV_PIX_FMT_GBRP10LE, + AV_PIX_FMT_GBRP12BE, + AV_PIX_FMT_GBRP12LE, + AV_PIX_FMT_GBRP14BE, + AV_PIX_FMT_GBRP14LE, + AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRAP10BE, + AV_PIX_FMT_GBRAP10LE, + AV_PIX_FMT_GBRAP12BE, + AV_PIX_FMT_GBRAP12LE, + AV_PIX_FMT_GBRP16BE, + AV_PIX_FMT_GBRP16LE, + AV_PIX_FMT_GBRAP16BE, + AV_PIX_FMT_GBRAP16LE, + AV_PIX_FMT_GBRPF32BE, + AV_PIX_FMT_GBRPF32LE, + AV_PIX_FMT_GBRAPF32BE, + AV_PIX_FMT_GBRAPF32LE +}; + +static void check_output_yuv2gbrp(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, fsi, isi, i; + int dstW, byte_size, luma_filter_size, chr_filter_size; +#define LARGEST_FILTER 16 +#define FILTER_SIZES 4 + static const int filter_sizes[] = {1, 4, 8, 16}; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *dst0[4]; + uint8_t *dst1[4]; + + declare_func(void, void *c, const int16_t *lumFilter, + const int16_t **lumSrcx, int lumFilterSize, + const int16_t *chrFilter, const int16_t **chrUSrcx, + const int16_t **chrVSrcx, int chrFilterSize, + const int16_t **alpSrcx, uint8_t **dest, + int dstW, int y); + + const int16_t *luma[LARGEST_FILTER]; + const int16_t *chru[LARGEST_FILTER]; + const int16_t *chrv[LARGEST_FILTER]; + const int16_t *alpha[LARGEST_FILTER]; + + LOCAL_ALIGNED_8(int16_t, luma_filter, [LARGEST_FILTER]); + LOCAL_ALIGNED_8(int16_t, chr_filter, [LARGEST_FILTER]); + + LOCAL_ALIGNED_8(int32_t, src_y, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_u, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_v, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_r, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_g, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_b, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + LOCAL_ALIGNED_8(uint8_t, dst1_r, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_g, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_b, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_y, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_u, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_v, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)luma_filter, LARGEST_FILTER * sizeof(int16_t)); + randomize_buffers((uint8_t*)chr_filter, LARGEST_FILTER * sizeof(int16_t)); + + dst0[0] = (uint8_t*)dst0_g; + dst0[1] = (uint8_t*)dst0_b; + dst0[2] = (uint8_t*)dst0_r; + dst0[3] = (uint8_t*)dst0_a; + + dst1[0] = (uint8_t*)dst1_g; + dst1[1] = (uint8_t*)dst1_b; + dst1[2] = (uint8_t*)dst1_r; + dst1[3] = (uint8_t*)dst1_a; + + for (i = 0; i < LARGEST_FILTER; i++) { + luma[i] = (int16_t *)(src_y + i*LARGEST_INPUT_SIZE); + chru[i] = (int16_t *)(src_u + i*LARGEST_INPUT_SIZE); + chrv[i] = (int16_t *)(src_v + i*LARGEST_INPUT_SIZE); + alpha[i] = (int16_t *)(src_a + i*LARGEST_INPUT_SIZE); + } + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + ctx->flags |= SWS_FULL_CHR_H_INT; + ctx->yuv2rgb_y_offset = rnd(); + ctx->yuv2rgb_y_coeff = rnd(); + ctx->yuv2rgb_v2r_coeff = rnd(); + ctx->yuv2rgb_v2g_coeff = rnd(); + ctx->yuv2rgb_u2g_coeff = rnd(); + ctx->yuv2rgb_u2b_coeff = rnd(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (fsi = 0; fsi < FILTER_SIZES; fsi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + ctx->dstFormat = planar_fmts[fmi]; + + dstW = input_sizes[isi]; + luma_filter_size = filter_sizes[fsi]; + chr_filter_size = filter_sizes[fsi]; + + if (desc->comp[0].depth > 16) { + byte_size = 4; + } else if (desc->comp[0].depth > 8) { + byte_size = 2; + } else { + byte_size = 1; + } + + ff_sws_init_scale(ctx); + if (check_func(ctx->yuv2anyX, "yuv2%s_full_X_%d_%d", desc->name, luma_filter_size, dstW)) { + for (i = 0; i < 4; i ++) { + memset(dst0[i], 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1[i], 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + } + + call_ref(ctx, luma_filter, luma, luma_filter_size, + chr_filter, chru, chrv, chr_filter_size, + alpha, dst0, dstW, 0); + call_new(ctx, luma_filter, luma, luma_filter_size, + chr_filter, chru, chrv, chr_filter_size, + alpha, dst1, dstW, 0); + + if (memcmp(dst0[0], dst1[0], dstW * byte_size) || + memcmp(dst0[1], dst1[1], dstW * byte_size) || + memcmp(dst0[2], dst1[2], dstW * byte_size) || + memcmp(dst0[3], dst1[3], dstW * byte_size) ) + fail(); + + bench_new(ctx, luma_filter, luma, luma_filter_size, + chr_filter, chru, chrv, chr_filter_size, + alpha, dst1, dstW, 0); + } + } + } + } + sws_freeContext(ctx); +} + + +void checkasm_check_sw_gbrp(void) +{ + check_output_yuv2gbrp(); + report("output_yuv2gbrp"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 6e7edbe655..6db8f09d12 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -26,6 +26,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-pixblockdsp \ fate-checkasm-sbrdsp \ fate-checkasm-synth_filter \ + fate-checkasm-sw_gbrp \ fate-checkasm-sw_rgb \ fate-checkasm-sw_scale \ fate-checkasm-utvideodsp \ From 52f70261642725f2b1af6e1a5a0b2c9d868997fa Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Wed, 24 Nov 2021 13:15:21 -0800 Subject: [PATCH 868/894] swscale/x86/input.asm: add x86-optimized planer rgb2yuv functions sse2 only operates on 2 lanes per loop for to_y and to_uv functions, due to the lack of pmulld instruction. Emulating pmulld with 2 pmuludq and shuffles proved too costly and made to_uv functions slower then the c implementation. For to_y on sse2 only float functions are generated, I was are not able outperform the c implementation on the integer pixel formats. For to_a on see4 only the float functions are generated. sse2 and sse4 generated nearly identical performing code on integer pixel formats, so only sse2/avx2 versions are generated. planar_gbrp_to_y_512_c: 1197.5 planar_gbrp_to_y_512_sse4: 444.5 planar_gbrp_to_y_512_avx2: 287.5 planar_gbrap_to_y_512_c: 1204.5 planar_gbrap_to_y_512_sse4: 447.5 planar_gbrap_to_y_512_avx2: 289.5 planar_gbrp9be_to_y_512_c: 1380.0 planar_gbrp9be_to_y_512_sse4: 543.5 planar_gbrp9be_to_y_512_avx2: 340.0 planar_gbrp9le_to_y_512_c: 1200.5 planar_gbrp9le_to_y_512_sse4: 442.0 planar_gbrp9le_to_y_512_avx2: 282.0 planar_gbrp10be_to_y_512_c: 1378.5 planar_gbrp10be_to_y_512_sse4: 544.0 planar_gbrp10be_to_y_512_avx2: 337.5 planar_gbrp10le_to_y_512_c: 1200.0 planar_gbrp10le_to_y_512_sse4: 448.0 planar_gbrp10le_to_y_512_avx2: 285.5 planar_gbrap10be_to_y_512_c: 1380.0 planar_gbrap10be_to_y_512_sse4: 542.0 planar_gbrap10be_to_y_512_avx2: 340.5 planar_gbrap10le_to_y_512_c: 1199.0 planar_gbrap10le_to_y_512_sse4: 446.0 planar_gbrap10le_to_y_512_avx2: 289.5 planar_gbrp12be_to_y_512_c: 10563.0 planar_gbrp12be_to_y_512_sse4: 542.5 planar_gbrp12be_to_y_512_avx2: 339.0 planar_gbrp12le_to_y_512_c: 1201.0 planar_gbrp12le_to_y_512_sse4: 440.5 planar_gbrp12le_to_y_512_avx2: 286.0 planar_gbrap12be_to_y_512_c: 1701.5 planar_gbrap12be_to_y_512_sse4: 917.0 planar_gbrap12be_to_y_512_avx2: 338.5 planar_gbrap12le_to_y_512_c: 1201.0 planar_gbrap12le_to_y_512_sse4: 444.5 planar_gbrap12le_to_y_512_avx2: 288.0 planar_gbrp14be_to_y_512_c: 1370.5 planar_gbrp14be_to_y_512_sse4: 545.0 planar_gbrp14be_to_y_512_avx2: 338.5 planar_gbrp14le_to_y_512_c: 1199.0 planar_gbrp14le_to_y_512_sse4: 444.0 planar_gbrp14le_to_y_512_avx2: 279.5 planar_gbrp16be_to_y_512_c: 1364.0 planar_gbrp16be_to_y_512_sse4: 544.5 planar_gbrp16be_to_y_512_avx2: 339.5 planar_gbrp16le_to_y_512_c: 1201.0 planar_gbrp16le_to_y_512_sse4: 445.5 planar_gbrp16le_to_y_512_avx2: 280.5 planar_gbrap16be_to_y_512_c: 1377.0 planar_gbrap16be_to_y_512_sse4: 545.0 planar_gbrap16be_to_y_512_avx2: 338.5 planar_gbrap16le_to_y_512_c: 1201.0 planar_gbrap16le_to_y_512_sse4: 442.0 planar_gbrap16le_to_y_512_avx2: 279.0 planar_gbrpf32be_to_y_512_c: 4113.0 planar_gbrpf32be_to_y_512_sse2: 2438.0 planar_gbrpf32be_to_y_512_sse4: 1068.0 planar_gbrpf32be_to_y_512_avx2: 904.5 planar_gbrpf32le_to_y_512_c: 3818.5 planar_gbrpf32le_to_y_512_sse2: 2024.5 planar_gbrpf32le_to_y_512_sse4: 1241.5 planar_gbrpf32le_to_y_512_avx2: 657.0 planar_gbrapf32be_to_y_512_c: 3707.0 planar_gbrapf32be_to_y_512_sse2: 2444.0 planar_gbrapf32be_to_y_512_sse4: 1077.0 planar_gbrapf32be_to_y_512_avx2: 909.0 planar_gbrapf32le_to_y_512_c: 3822.0 planar_gbrapf32le_to_y_512_sse2: 2024.5 planar_gbrapf32le_to_y_512_sse4: 1176.0 planar_gbrapf32le_to_y_512_avx2: 658.5 planar_gbrp_to_uv_512_c: 2325.8 planar_gbrp_to_uv_512_sse2: 1726.8 planar_gbrp_to_uv_512_sse4: 771.8 planar_gbrp_to_uv_512_avx2: 506.8 planar_gbrap_to_uv_512_c: 2281.8 planar_gbrap_to_uv_512_sse2: 1726.3 planar_gbrap_to_uv_512_sse4: 768.3 planar_gbrap_to_uv_512_avx2: 496.3 planar_gbrp9be_to_uv_512_c: 2336.8 planar_gbrp9be_to_uv_512_sse2: 1924.8 planar_gbrp9be_to_uv_512_sse4: 852.3 planar_gbrp9be_to_uv_512_avx2: 552.8 planar_gbrp9le_to_uv_512_c: 2270.3 planar_gbrp9le_to_uv_512_sse2: 1512.3 planar_gbrp9le_to_uv_512_sse4: 764.3 planar_gbrp9le_to_uv_512_avx2: 491.3 planar_gbrp10be_to_uv_512_c: 2281.8 planar_gbrp10be_to_uv_512_sse2: 1917.8 planar_gbrp10be_to_uv_512_sse4: 855.3 planar_gbrp10be_to_uv_512_avx2: 541.3 planar_gbrp10le_to_uv_512_c: 2269.8 planar_gbrp10le_to_uv_512_sse2: 1515.3 planar_gbrp10le_to_uv_512_sse4: 759.8 planar_gbrp10le_to_uv_512_avx2: 487.8 planar_gbrap10be_to_uv_512_c: 2382.3 planar_gbrap10be_to_uv_512_sse2: 1924.8 planar_gbrap10be_to_uv_512_sse4: 855.3 planar_gbrap10be_to_uv_512_avx2: 540.8 planar_gbrap10le_to_uv_512_c: 2382.3 planar_gbrap10le_to_uv_512_sse2: 1512.3 planar_gbrap10le_to_uv_512_sse4: 759.3 planar_gbrap10le_to_uv_512_avx2: 484.8 planar_gbrp12be_to_uv_512_c: 2283.8 planar_gbrp12be_to_uv_512_sse2: 1936.8 planar_gbrp12be_to_uv_512_sse4: 858.3 planar_gbrp12be_to_uv_512_avx2: 541.3 planar_gbrp12le_to_uv_512_c: 2278.8 planar_gbrp12le_to_uv_512_sse2: 1507.3 planar_gbrp12le_to_uv_512_sse4: 760.3 planar_gbrp12le_to_uv_512_avx2: 485.8 planar_gbrap12be_to_uv_512_c: 2385.3 planar_gbrap12be_to_uv_512_sse2: 1927.8 planar_gbrap12be_to_uv_512_sse4: 855.3 planar_gbrap12be_to_uv_512_avx2: 539.8 planar_gbrap12le_to_uv_512_c: 2377.3 planar_gbrap12le_to_uv_512_sse2: 1516.3 planar_gbrap12le_to_uv_512_sse4: 759.3 planar_gbrap12le_to_uv_512_avx2: 484.8 planar_gbrp14be_to_uv_512_c: 2283.8 planar_gbrp14be_to_uv_512_sse2: 1935.3 planar_gbrp14be_to_uv_512_sse4: 852.3 planar_gbrp14be_to_uv_512_avx2: 540.3 planar_gbrp14le_to_uv_512_c: 2276.8 planar_gbrp14le_to_uv_512_sse2: 1514.8 planar_gbrp14le_to_uv_512_sse4: 762.3 planar_gbrp14le_to_uv_512_avx2: 484.8 planar_gbrp16be_to_uv_512_c: 2383.3 planar_gbrp16be_to_uv_512_sse2: 1881.8 planar_gbrp16be_to_uv_512_sse4: 852.3 planar_gbrp16be_to_uv_512_avx2: 541.8 planar_gbrp16le_to_uv_512_c: 2378.3 planar_gbrp16le_to_uv_512_sse2: 1476.8 planar_gbrp16le_to_uv_512_sse4: 765.3 planar_gbrp16le_to_uv_512_avx2: 485.8 planar_gbrap16be_to_uv_512_c: 2382.3 planar_gbrap16be_to_uv_512_sse2: 1886.3 planar_gbrap16be_to_uv_512_sse4: 853.8 planar_gbrap16be_to_uv_512_avx2: 550.8 planar_gbrap16le_to_uv_512_c: 2381.8 planar_gbrap16le_to_uv_512_sse2: 1488.3 planar_gbrap16le_to_uv_512_sse4: 765.3 planar_gbrap16le_to_uv_512_avx2: 491.8 planar_gbrpf32be_to_uv_512_c: 4863.0 planar_gbrpf32be_to_uv_512_sse2: 3347.5 planar_gbrpf32be_to_uv_512_sse4: 1800.0 planar_gbrpf32be_to_uv_512_avx2: 1199.0 planar_gbrpf32le_to_uv_512_c: 4725.0 planar_gbrpf32le_to_uv_512_sse2: 2753.0 planar_gbrpf32le_to_uv_512_sse4: 1474.5 planar_gbrpf32le_to_uv_512_avx2: 927.5 planar_gbrapf32be_to_uv_512_c: 4859.0 planar_gbrapf32be_to_uv_512_sse2: 3269.0 planar_gbrapf32be_to_uv_512_sse4: 1802.0 planar_gbrapf32be_to_uv_512_avx2: 1201.5 planar_gbrapf32le_to_uv_512_c: 6338.0 planar_gbrapf32le_to_uv_512_sse2: 2756.5 planar_gbrapf32le_to_uv_512_sse4: 1476.0 planar_gbrapf32le_to_uv_512_avx2: 908.5 planar_gbrap_to_a_512_c: 383.3 planar_gbrap_to_a_512_sse2: 66.8 planar_gbrap_to_a_512_avx2: 43.8 planar_gbrap10be_to_a_512_c: 601.8 planar_gbrap10be_to_a_512_sse2: 86.3 planar_gbrap10be_to_a_512_avx2: 34.8 planar_gbrap10le_to_a_512_c: 602.3 planar_gbrap10le_to_a_512_sse2: 48.8 planar_gbrap10le_to_a_512_avx2: 31.3 planar_gbrap12be_to_a_512_c: 601.8 planar_gbrap12be_to_a_512_sse2: 111.8 planar_gbrap12be_to_a_512_avx2: 41.3 planar_gbrap12le_to_a_512_c: 385.8 planar_gbrap12le_to_a_512_sse2: 75.3 planar_gbrap12le_to_a_512_avx2: 39.8 planar_gbrap16be_to_a_512_c: 386.8 planar_gbrap16be_to_a_512_sse2: 79.8 planar_gbrap16be_to_a_512_avx2: 31.3 planar_gbrap16le_to_a_512_c: 600.3 planar_gbrap16le_to_a_512_sse2: 40.3 planar_gbrap16le_to_a_512_avx2: 30.3 planar_gbrapf32be_to_a_512_c: 1148.8 planar_gbrapf32be_to_a_512_sse2: 611.3 planar_gbrapf32be_to_a_512_sse4: 234.8 planar_gbrapf32be_to_a_512_avx2: 183.3 planar_gbrapf32le_to_a_512_c: 851.3 planar_gbrapf32le_to_a_512_sse2: 263.3 planar_gbrapf32le_to_a_512_sse4: 199.3 planar_gbrapf32le_to_a_512_avx2: 156.8 Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libswscale/x86/input.asm | 484 ++++++++++++++++++++++++++++++++++++++- libswscale/x86/swscale.c | 170 ++++++++++++++ tests/checkasm/sw_gbrp.c | 216 +++++++++++++++++ 3 files changed, 869 insertions(+), 1 deletion(-) diff --git a/libswscale/x86/input.asm b/libswscale/x86/input.asm index af9afcaa53..fcdfe2fcd8 100644 --- a/libswscale/x86/input.asm +++ b/libswscale/x86/input.asm @@ -93,7 +93,31 @@ shuf_rgb_12x4: db 0, 0x80, 1, 0x80, 2, 0x80, 3, 0x80, \ 6, 0x80, 7, 0x80, 8, 0x80, 9, 0x80 shuf_rgb_3x56: db 2, 0x80, 3, 0x80, 4, 0x80, 5, 0x80, \ 8, 0x80, 9, 0x80, 10, 0x80, 11, 0x80 - +pd_65535f: times 8 dd 65535.0 +pb_pack_shuffle16le: db 0, 1, 4, 5, \ + 8, 9, 12, 13, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 0, 1, 4, 5, \ + 8, 9, 12, 13 +pb_shuffle32be: db 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12, \ + 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12 +pb_shuffle16be: db 1, 0, 3, 2, \ + 5, 4, 7, 6, \ + 9, 8, 11, 10, \ + 13, 12, 15, 14, \ + 1, 0, 3, 2, \ + 5, 4, 7, 6, \ + 9, 8, 11, 10, \ + 13, 12, 15, 14 SECTION .text ;----------------------------------------------------------------------------- @@ -738,3 +762,461 @@ YUYV_TO_UV_FN 3, uyvy, 1 NVXX_TO_UV_FN 5, nv12 NVXX_TO_UV_FN 5, nv21 %endif + +%if ARCH_X86_64 +%define RY_IDX 0 +%define GY_IDX 1 +%define BY_IDX 2 +%define RU_IDX 3 +%define GU_IDX 4 +%define BU_IDX 5 +%define RV_IDX 6 +%define GV_IDX 7 +%define BV_IDX 8 +%define RGB2YUV_SHIFT 15 + +%define R m0 +%define G m1 +%define B m2 + +%macro SWAP32 1 +%if mmsize > 16 || cpuflag(sse4) + pshufb m%1, [pb_shuffle32be] +%else + psrlw xm7, xm%1, 8 + psllw xm%1, 8 + por xm%1, xm7 + pshuflw xm%1, xm%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) + pshufhw xm%1, xm%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) +%endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - is big endian +; 4 - load only 2 values on sse2 +%macro LOADF32 4 + %if notcpuflag(sse4) && %4 + %if %3 ; big endian + mov tmp1q, %2 + bswap tmp1q + movq xm%1, tmp1q + %else + movq m%1, %2 + %endif + %else + movu m%1, %2 + %if %3 + SWAP32 %1 + %endif + %endif + maxps m%1, m9 ; 0.0 (nan, -inf) -> 0.0 + mulps m%1, m8 ; [pd_65535f] + minps m%1, m8 ; +inf -> 65535 + ; cvtps2dq rounds to nearest int + ; assuming mxcsr register is default rounding + ; 0.40 -> 0.0, 0.50 -> 0.0, 0.51 -> 1.0 + cvtps2dq m%1, m%1 + + %if notcpuflag(sse4) && %4 + ; line up the 2 values in lanes 0,2 + %if %3 ; big endian + pshufd m%1, m%1, (3 << 6 | 0 << 4 | 2 << 2 | 1 << 0) + %else + pshufd m%1, m%1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %endif + %endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - is big endian +%macro LOAD16 3 + %if cpuflag(sse4) || mmsize > 16 + pmovzxwd m%1, %2 + %if %3 ; bigendian + pshufb m%1, m8 ; [pb_shuffle16be] + %endif + %else + %if %3 ; bigendian + mov tmp1d, dword %2 + bswap tmp1d + movd xm%1, tmp1d + pshuflw m%1, m%1, (3 << 6 | 0 << 4 | 3 << 2 | 1 << 0) + pshufd m%1, m%1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %else + movd xm%1, %2 + punpcklwd m%1, m9 ; interleave words with zero + pshufd m%1, m%1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %endif + %endif +%endmacro + +%macro LOAD8_RGB 0 + %if cpuflag(sse4) || mmsize > 16 + pmovzxbd R, [srcRq + xq] + pmovzxbd G, [srcGq + xq] + pmovzxbd B, [srcBq + xq] + %else + ; thought this would be faster but from my measurments its not + ; movd m0, [srcRq + xq + 0]; overeads by 2 bytes + ; punpcklbw m0, m9 ; interleave bytes with zero + ; punpcklwd m0, m9 ; interleave words with zero + ; pshufd m0, m0, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + + movzx tmp2q, byte [srcRq + xq + 1] + movzx tmp1q, byte [srcRq + xq + 0] + shl tmp2q, 32 + or tmp1q, tmp2q + movq xm0, tmp1q + + movzx tmp2q, byte [srcGq + xq + 1] + movzx tmp3q, byte [srcGq + xq + 0] + shl tmp2q, 32 + or tmp3q, tmp2q + movq xm1, tmp3q + + movzx tmp2q, byte [srcBq + xq + 1] + movzx tmp1q, byte [srcBq + xq + 0] + shl tmp2q, 32 + or tmp1q, tmp2q + movq xm2, tmp1q + + pshufd m0, m0, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m1, m1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m2, m2, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - store only 2 values on sse2 +%macro STORE16 3 + %if %3 && notcpuflag(sse4) + pshufd m%2, m%2, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshuflw m%2, m%2, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + movd %1, m%2 + %elif mmsize > 16 + pshufb m%2, m7 ; [pb_pack_shuffle16le] + vpermq m%2, m%2, (3 << 6 | 0 << 4 | 3 << 2 | 0 << 0) + movu %1, xm%2 + %else + %if cpuflag(sse4) + pshufb m%2, m7 ; [pb_pack_shuffle16le] + %else + pshuflw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufhw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m%2, m%2, (3 << 6 | 3 << 4 | 2 << 2 | 0 << 0) + %endif + movq %1, m%2 + %endif +%endmacro + +%macro PMUL 3 +%if cpuflag(sse4) || mmsize > 16 + pmulld %1, %2, %3 +%else + pmuludq %1, %2, %3 +%endif +%endmacro + +; 1 - name +; 2 - depth +; 3 - is big endian +; 4 - is float +; in sse2 mode only 2 values are done per loop, due to lack of pmulld instruction +%macro planar_rgb_to_y_fn 4 +%if %2 == 8 + %define OFFSET (0x801<<(RGB2YUV_SHIFT-7)) + %define RSHIFT (RGB2YUV_SHIFT-6) +%else + %if %2 < 16 + %define SHIFT %2 + %define BPC %2 + %else + %define SHIFT 14 + %define BPC 16 + %endif + %define OFFSET ((16 << (RGB2YUV_SHIFT + BPC - 8)) + (1 << (RGB2YUV_SHIFT + SHIFT - 15))) + %define RSHIFT (RGB2YUV_SHIFT + SHIFT - 14) +%endif +cglobal planar_%1_to_y, 4, 12, 13, dst, src, w, rgb2yuv, srcR, srcG, srcB, x, tmp1, tmp2, tmp3, tmp4 + VBROADCASTSS m10, dword [rgb2yuvq + RY_IDX*4] ; ry + VBROADCASTSS m11, dword [rgb2yuvq + GY_IDX*4] ; gy + VBROADCASTSS m12, dword [rgb2yuvq + BY_IDX*4] ; by + pxor m9, m9 + + %if %4 + movu m8, [pd_65535f] + %endif + + %if cpuflag(sse4) || mmsize > 16 + movu m7, [pb_pack_shuffle16le] + %if %3 && %2 > 8 && %2 <= 16 + movu m8, [pb_shuffle16be] + %endif + %endif + + mov xq, OFFSET + movq xm6, xq + VBROADCASTSS m6, xm6 + + mov srcGq, [srcq + 0] + mov srcBq, [srcq + 8] + mov srcRq, [srcq + 16] + + xor xq, xq + %%loop_x: + %if %4 + LOADF32 0, [srcRq + xq*4], %3, 1 + LOADF32 1, [srcGq + xq*4], %3, 1 + LOADF32 2, [srcBq + xq*4], %3, 1 + %elif %2 == 8 + LOAD8_RGB + %else + LOAD16 0, [srcRq + xq*2], %3 + LOAD16 1, [srcGq + xq*2], %3 + LOAD16 2, [srcBq + xq*2], %3 + %endif + + PMUL R, R, m10 ; r*ry + PMUL G, G, m11 ; g*gy + PMUL B, B, m12 ; b*by + paddd m0, m6 ; + OFFSET + paddd B, G + paddd m0, B + psrad m0, RSHIFT + STORE16 [dstq + 2*xq], 0, 1 + + %if cpuflag(avx2) || cpuflag(sse4) + add xq, mmsize/4 + %else + add xd, 2 + %endif + cmp xd, wd + jl %%loop_x +RET +%endmacro + +; 1 - name +; 2 - depth +; 3 - is big endian +; 4 - is float +; in sse2 mode only 2 values are done per loop, due to lack of pmulld instruction +%macro planar_rgb_to_uv_fn 4 +%if %2 == 8 + %define OFFSET (0x4001<<(RGB2YUV_SHIFT-7)) + %define RSHIFT (RGB2YUV_SHIFT-6) +%else + %if %2 < 16 + %define SHIFT %2 + %define BPC %2 + %else + %define SHIFT 14 + %define BPC 16 + %endif + %define OFFSET ((128 << (RGB2YUV_SHIFT + BPC - 8)) + (1 << (RGB2YUV_SHIFT + SHIFT - 15))) + %define RSHIFT (RGB2YUV_SHIFT + SHIFT - 14) +%endif +cglobal planar_%1_to_uv, 5, 12, 16, dstU, dstV, src, w, rgb2yuv, srcR, srcG, srcB, x, tmp1, tmp2, tmp3 + VBROADCASTSS m10, dword [rgb2yuvq + RU_IDX*4] ; ru + VBROADCASTSS m11, dword [rgb2yuvq + GU_IDX*4] ; gu + VBROADCASTSS m12, dword [rgb2yuvq + BU_IDX*4] ; bu + VBROADCASTSS m13, dword [rgb2yuvq + RV_IDX*4] ; rv + VBROADCASTSS m14, dword [rgb2yuvq + GV_IDX*4] ; gv + VBROADCASTSS m15, dword [rgb2yuvq + BV_IDX*4] ; bv + pxor m9, m9 + + %if %4 + movu m8, [pd_65535f] + %endif + + %if cpuflag(sse4) || mmsize > 16 + movu m7, [pb_pack_shuffle16le] + %if %3 && %2 > 8 && %2 <= 16 + movu m8, [pb_shuffle16be] + %endif + %endif + + mov xq, OFFSET + movq xm6, xq + VBROADCASTSS m6, xm6 + + mov srcGq, [srcq + 0] + mov srcBq, [srcq + 8] + mov srcRq, [srcq + 16] + + xor xq, xq + %%loop_x: + %if %4 + LOADF32 0, [srcRq + xq*4], %3, 1 + LOADF32 1, [srcGq + xq*4], %3, 1 + LOADF32 2, [srcBq + xq*4], %3, 1 + %elif %2 == 8 + LOAD8_RGB + %else + LOAD16 0, [srcRq + xq*2], %3 + LOAD16 1, [srcGq + xq*2], %3 + LOAD16 2, [srcBq + xq*2], %3 + %endif + + PMUL m5, R, m10 ; r*ru + PMUL m4, G, m11 ; b*gu + paddd m4, m5 + PMUL m5, B, m12 ; b*bu + paddd m4, m6 ; + OFFSET + paddd m4, m5 + psrad m4, RSHIFT + STORE16 [dstUq + 2*xq], 4, 1 + + PMUL R, R, m13 ; r*rv + PMUL G, G, m14 ; g*gv*g + PMUL B, B, m15 ; b*bv + paddd m0, m6 ; + OFFSET + paddd B, G + paddd m0, B + psrad m0, RSHIFT + STORE16 [dstVq + 2*xq], 0, 1 + + %if cpuflag(avx2) || cpuflag(sse4) + add xd, mmsize/4 + %else + add xd, 2 + %endif + cmp xd, wd + jl %%loop_x +RET +%endmacro + +; 1 - name +; 2 - depth +; 3 - is big endian +; 4 - is float +%macro planar_rgb_to_a_fn 4 +cglobal planar_%1_to_a, 4, 6, 10, dst, src, w, rgb2yuv, srcA, x + %if %4 && (cpuflag(sse4) || mmsize > 16) + movu m7, [pb_pack_shuffle16le] + %elif %3 && (cpuflag(sse4) || mmsize > 16) + movu m7, [pb_shuffle16be] + %endif + + %if %4 + movu m8, [pd_65535f] + %endif + + pxor m9, m9 + mov srcAq, [srcq + 24] + xor xq, xq + %%loop_x: + %if %4 ; float + LOADF32 0, [srcAq + xq*4], %3, 0 + STORE16 [dstq + xq*2], 0, 0 + add xq, mmsize/4 + %elif %2 == 8 + ; only need to convert 8bit value to 16bit + %if cpuflag(sse4) || mmsize > 16 + pmovzxbw m0, [srcAq + xq] + %else + movsd m0, [srcAq + xq] + punpcklbw m0, m9 ; interleave bytes with zero + %endif + psllw m0, 6 + movu [dstq + xq*2], m0 + add xq, mmsize/2 + %else + ; only need to convert 16bit format to 16le + movu m0, [srcAq + xq*2] + %if %3 ; bigendian + %if cpuflag(sse4) || mmsize > 16 + pshufb m0, m7 ; [pb_shuffle16be] + %else + psrlw m7, m0, 8 + psllw m0, 8 + por m0, m7 + %endif + %endif + %if %2 < 16 + psllw m0, (14 - %2) + %endif + movu [dstq + xq*2], m0 + add xq, mmsize/2 + %endif + cmp xd, wd + jl %%loop_x +RET +%endmacro + +; 1 - name +; 2 - depth +; 3 - is float +%macro planer_rgbxx_y_fn_decl 3 +planar_rgb_to_y_fn %1le, %2, 0, %3 +planar_rgb_to_y_fn %1be, %2, 1, %3 +%endmacro + +; 1 - name +; 2 - depth +; 3 - is float +%macro planer_rgbxx_uv_fn_decl 3 +planar_rgb_to_uv_fn %1le, %2, 0, %3 +planar_rgb_to_uv_fn %1be, %2, 1, %3 +%endmacro + +; 1 - name +; 2 - depth +; 3 - is float +%macro planer_rgbxx_a_fn_decl 3 +planar_rgb_to_a_fn %1le, %2, 0, %3 +planar_rgb_to_a_fn %1be, %2, 1, %3 +%endmacro + +%macro planar_rgb_y_all_fn_decl 0 +planar_rgb_to_y_fn rgb, 8, 0, 0 +planer_rgbxx_y_fn_decl rgb9, 9, 0 +planer_rgbxx_y_fn_decl rgb10, 10, 0 +planer_rgbxx_y_fn_decl rgb12, 12, 0 +planer_rgbxx_y_fn_decl rgb14, 14, 0 +planer_rgbxx_y_fn_decl rgb16, 16, 0 +planer_rgbxx_y_fn_decl rgbf32, 32, 1 +%endmacro + +%macro planar_rgb_uv_all_fn_decl 0 +planar_rgb_to_uv_fn rgb, 8, 0, 0 +planer_rgbxx_uv_fn_decl rgb9, 9, 0 +planer_rgbxx_uv_fn_decl rgb10, 10, 0 +planer_rgbxx_uv_fn_decl rgb12, 12, 0 +planer_rgbxx_uv_fn_decl rgb14, 14, 0 +planer_rgbxx_uv_fn_decl rgb16, 16, 0 +planer_rgbxx_uv_fn_decl rgbf32, 32, 1 +%endmacro + +%macro planar_rgb_a_all_fn_decl 0 +planar_rgb_to_a_fn rgb, 8, 0, 0 +planer_rgbxx_a_fn_decl rgb10, 10, 0 +planer_rgbxx_a_fn_decl rgb12, 12, 0 +planer_rgbxx_a_fn_decl rgb16, 16, 0 +planer_rgbxx_a_fn_decl rgbf32, 32, 1 +%endmacro + +; sse2 to_y only matches c speed with current implementation +; except on floating point formats +INIT_XMM sse2 +planer_rgbxx_y_fn_decl rgbf32, 32, 1 +planar_rgb_uv_all_fn_decl +planar_rgb_a_all_fn_decl + +; sse4 to_a conversions are just the sse2 ones +; except on floating point formats +INIT_XMM sse4 +planar_rgb_y_all_fn_decl +planar_rgb_uv_all_fn_decl +planer_rgbxx_a_fn_decl rgbf32, 32, 1 + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +planar_rgb_y_all_fn_decl +planar_rgb_uv_all_fn_decl +planar_rgb_a_all_fn_decl +%endif + +%endif ; ARCH_X86_64 diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index d5a467da0e..3cf0c419fd 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -390,6 +390,80 @@ YUV2GBRP_DECL(sse2); YUV2GBRP_DECL(sse4); YUV2GBRP_DECL(avx2); +#define INPUT_PLANAR_RGB_Y_FN_DECL(fmt, opt) \ +void ff_planar_##fmt##_to_y_##opt(uint8_t *dst, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) + +#define INPUT_PLANAR_RGB_UV_FN_DECL(fmt, opt) \ +void ff_planar_##fmt##_to_uv_##opt(uint8_t *dstU, uint8_t *dstV, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) + +#define INPUT_PLANAR_RGB_A_FN_DECL(fmt, opt) \ +void ff_planar_##fmt##_to_a_##opt(uint8_t *dst, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) + + +#define INPUT_PLANAR_RGBXX_A_DECL(fmt, opt) \ +INPUT_PLANAR_RGB_A_FN_DECL(fmt##le, opt); \ +INPUT_PLANAR_RGB_A_FN_DECL(fmt##be, opt); + +#define INPUT_PLANAR_RGBXX_Y_DECL(fmt, opt) \ +INPUT_PLANAR_RGB_Y_FN_DECL(fmt##le, opt); \ +INPUT_PLANAR_RGB_Y_FN_DECL(fmt##be, opt); + +#define INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt) \ +INPUT_PLANAR_RGB_UV_FN_DECL(fmt##le, opt); \ +INPUT_PLANAR_RGB_UV_FN_DECL(fmt##be, opt); + +#define INPUT_PLANAR_RGBXX_YUVA_DECL(fmt, opt) \ +INPUT_PLANAR_RGBXX_Y_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(fmt, opt); + +#define INPUT_PLANAR_RGBXX_YUV_DECL(fmt, opt) \ +INPUT_PLANAR_RGBXX_Y_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt); + +#define INPUT_PLANAR_RGBXX_UVA_DECL(fmt, opt) \ +INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(fmt, opt); + +#define INPUT_PLANAR_RGB_A_ALL_DECL(opt) \ +INPUT_PLANAR_RGB_A_FN_DECL(rgb, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgb10, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgb12, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgb16, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgbf32, opt); + +#define INPUT_PLANAR_RGB_Y_ALL_DECL(opt) \ +INPUT_PLANAR_RGB_Y_FN_DECL(rgb, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb9, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb10, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb12, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb14, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb16, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgbf32, opt); + +#define INPUT_PLANAR_RGB_UV_ALL_DECL(opt) \ +INPUT_PLANAR_RGB_UV_FN_DECL(rgb, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb9, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb10, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb12, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb14, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb16, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgbf32, opt); + +INPUT_PLANAR_RGBXX_Y_DECL(rgbf32, sse2); +INPUT_PLANAR_RGB_UV_ALL_DECL(sse2); +INPUT_PLANAR_RGB_A_ALL_DECL(sse2); + +INPUT_PLANAR_RGB_Y_ALL_DECL(sse4); +INPUT_PLANAR_RGB_UV_ALL_DECL(sse4); +INPUT_PLANAR_RGBXX_A_DECL(rgbf32, sse4); + +INPUT_PLANAR_RGB_Y_ALL_DECL(avx2); +INPUT_PLANAR_RGB_UV_ALL_DECL(avx2); +INPUT_PLANAR_RGB_A_ALL_DECL(avx2); #endif av_cold void ff_sws_init_swscale_x86(SwsContext *c) @@ -639,6 +713,102 @@ switch(c->dstBpc){ \ } } + +#define INPUT_PLANER_RGB_A_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->readAlpPlanar = ff_planar_##name##_to_a_##opt; + +#define INPUT_PLANER_RGBA_YUV_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + case rgba_fmt: \ + case rgb_fmt: \ + c->readLumPlanar = ff_planar_##name##_to_y_##opt; \ + c->readChrPlanar = ff_planar_##name##_to_uv_##opt; \ + break; + +#define INPUT_PLANER_RGB_YUV_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->readLumPlanar = ff_planar_##name##_to_y_##opt; \ + c->readChrPlanar = ff_planar_##name##_to_uv_##opt; \ + break; + +#define INPUT_PLANER_RGB_UV_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->readChrPlanar = ff_planar_##name##_to_uv_##opt; \ + break; + +#define INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##BE, name##be, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBAXX_UVA_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##BE, name##be, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBAXX_YUV_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + INPUT_PLANER_RGBA_YUV_FUNC_CASE(rgb_fmt##LE, rgba_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGBA_YUV_FUNC_CASE(rgb_fmt##BE, rgba_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBXX_YUV_FUNC_CASE(rgb_fmt, name, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBXX_UV_FUNC_CASE(rgb_fmt, name, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGB_YUVA_ALL_CASES(opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE( AV_PIX_FMT_GBRAP, rgb, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, opt) \ + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, rgb10, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, rgb12, opt) \ + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP14, rgb14, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, rgb16, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, rgbf32, opt) + + + if (EXTERNAL_SSE2(cpu_flags)) { + switch (c->srcFormat) { + INPUT_PLANER_RGB_A_FUNC_CASE( AV_PIX_FMT_GBRAP, rgb, sse2); + INPUT_PLANER_RGB_UV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, sse2); + INPUT_PLANER_RGBXX_UV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, sse2); + INPUT_PLANER_RGBAXX_UVA_FUNC_CASE( AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, rgb10, sse2); + INPUT_PLANER_RGBAXX_UVA_FUNC_CASE( AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, rgb12, sse2); + INPUT_PLANER_RGBXX_UV_FUNC_CASE( AV_PIX_FMT_GBRP14, rgb14, sse2); + INPUT_PLANER_RGBAXX_UVA_FUNC_CASE( AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, rgb16, sse2); + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, rgbf32, sse2); + default: + break; + } + } + + if (EXTERNAL_SSE4(cpu_flags)) { + switch (c->srcFormat) { + case AV_PIX_FMT_GBRAP: + INPUT_PLANER_RGB_YUV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, sse4); + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, sse4); + INPUT_PLANER_RGBAXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, rgb10, sse4); + INPUT_PLANER_RGBAXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, rgb12, sse4); + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP14, rgb14, sse4); + INPUT_PLANER_RGBAXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, rgb16, sse4); + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, rgbf32, sse4); + default: + break; + } + } + + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + switch (c->srcFormat) { + INPUT_PLANER_RGB_YUVA_ALL_CASES(avx2) + default: + break; + } + } + if(c->flags & SWS_FULL_CHR_H_INT) { /* yuv2gbrp uses the SwsContext for yuv coefficients diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c index 61b2b9d6a1..848e5366ad 100644 --- a/tests/checkasm/sw_gbrp.c +++ b/tests/checkasm/sw_gbrp.c @@ -190,9 +190,225 @@ static void check_output_yuv2gbrp(void) sws_freeContext(ctx); } +#undef LARGEST_INPUT_SIZE +#undef INPUT_SIZES + +static void check_input_planar_rgb_to_y(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, isi; + int dstW, byte_size; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *src[4]; + int32_t rgb2yuv[9] = {0}; + + declare_func(void, uint8_t *dst, uint8_t *src[4], int w, int32_t *rgb2yuv); + + LOCAL_ALIGNED_8(int32_t, src_r, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_g, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_b, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_y, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_y, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_r, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_g, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_b, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)rgb2yuv, 9 * sizeof(int32_t)); + + src[0] = (uint8_t*)src_g; + src[1] = (uint8_t*)src_b; + src[2] = (uint8_t*)src_r; + src[3] = (uint8_t*)src_a; + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + ctx->srcFormat = planar_fmts[fmi]; + ctx->dstFormat = AV_PIX_FMT_YUVA444P16; + byte_size = 2; + dstW = input_sizes[isi]; + + ff_sws_init_scale(ctx); + if(check_func(ctx->readLumPlanar, "planar_%s_to_y_%d", desc->name, dstW)) { + memset(dst0_y, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_y, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + + call_ref(dst0_y, src, dstW, rgb2yuv); + call_new(dst1_y, src, dstW, rgb2yuv); + + if (memcmp(dst0_y, dst1_y, dstW * byte_size)) + fail(); + + bench_new(dst1_y, src, dstW, rgb2yuv); + + } + } + } + sws_freeContext(ctx); +} + +#undef LARGEST_INPUT_SIZE +#undef INPUT_SIZES + +static void check_input_planar_rgb_to_uv(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, isi; + int dstW, byte_size; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *src[4]; + int32_t rgb2yuv[9] = {0}; + + declare_func(void, uint8_t *dstU, uint8_t *dstV, + uint8_t *src[4], int w, int32_t *rgb2yuv); + + LOCAL_ALIGNED_8(int32_t, src_r, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_g, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_b, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_u, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_v, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + LOCAL_ALIGNED_8(uint8_t, dst1_u, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_v, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_r, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_g, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_b, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)rgb2yuv, 9 * sizeof(int32_t)); + + src[0] = (uint8_t*)src_g; + src[1] = (uint8_t*)src_b; + src[2] = (uint8_t*)src_r; + src[3] = (uint8_t*)src_a; + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + ctx->srcFormat = planar_fmts[fmi]; + ctx->dstFormat = AV_PIX_FMT_YUVA444P16; + byte_size = 2; + dstW = input_sizes[isi]; + + ff_sws_init_scale(ctx); + if(check_func(ctx->readChrPlanar, "planar_%s_to_uv_%d", desc->name, dstW)) { + memset(dst0_u, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst0_v, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_u, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_v, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + + call_ref(dst0_u, dst0_v, src, dstW, rgb2yuv); + call_new(dst1_u, dst1_v, src, dstW, rgb2yuv); + + if (memcmp(dst0_u, dst1_u, dstW * byte_size) || + memcmp(dst0_v, dst1_v, dstW * byte_size)) + fail(); + + bench_new(dst1_u, dst1_v, src, dstW, rgb2yuv); + } + } + } + sws_freeContext(ctx); +} + +#undef LARGEST_INPUT_SIZE +#undef INPUT_SIZES + +static void check_input_planar_rgb_to_a(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, isi; + int dstW, byte_size; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *src[4]; + int32_t rgb2yuv[9] = {0}; + + declare_func(void, uint8_t *dst, uint8_t *src[4], int w, int32_t *rgb2yuv); + + LOCAL_ALIGNED_8(int32_t, src_r, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_g, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_b, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_r, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_g, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_b, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)rgb2yuv, 9 * sizeof(int32_t)); + + src[0] = (uint8_t*)src_g; + src[1] = (uint8_t*)src_b; + src[2] = (uint8_t*)src_r; + src[3] = (uint8_t*)src_a; + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) + continue; + + ctx->srcFormat = planar_fmts[fmi]; + ctx->dstFormat = AV_PIX_FMT_YUVA444P16; + byte_size = 2; + dstW = input_sizes[isi]; + + ff_sws_init_scale(ctx); + if(check_func(ctx->readAlpPlanar, "planar_%s_to_a_%d", desc->name, dstW)) { + memset(dst0_a, 0x00, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_a, 0x00, LARGEST_INPUT_SIZE * sizeof(int32_t)); + + call_ref(dst0_a, src, dstW, rgb2yuv); + call_new(dst1_a, src, dstW, rgb2yuv); + + if (memcmp(dst0_a, dst1_a, dstW * byte_size)) + fail(); + bench_new(dst1_a, src, dstW, rgb2yuv); + } + } + } + sws_freeContext(ctx); +} void checkasm_check_sw_gbrp(void) { check_output_yuv2gbrp(); report("output_yuv2gbrp"); + + check_input_planar_rgb_to_y(); + report("input_planar_rgb_y"); + + check_input_planar_rgb_to_uv(); + report("input_planar_rgb_uv"); + + check_input_planar_rgb_to_a(); + report("input_planar_rgb_a"); } From 824fdd0f89b7ffe2753bf648e8c56cf09a71edf0 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 1 Jan 2022 20:19:40 +0800 Subject: [PATCH 869/894] avformat/rtpdec_rfc4175: support for interlace format Signed-off-by: Limin Wang --- libavformat/rtpdec_rfc4175.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index a66e00d5fe..e0a708e437 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -33,6 +33,8 @@ struct PayloadContext { int depth; int width; int height; + int interlaced; + int field; uint8_t *frame; unsigned int frame_size; @@ -104,6 +106,11 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data) stream->codecpar->bits_per_coded_sample = av_get_bits_per_pixel(desc); data->frame_size = data->width * data->height * data->pgroup / data->xinc; + if (data->interlaced) + stream->codecpar->field_order = AV_FIELD_TT; + else + stream->codecpar->field_order = AV_FIELD_PROGRESSIVE; + if (data->framerate.den > 0) { stream->avg_frame_rate = data->framerate; stream->codecpar->bit_rate = data->frame_size * av_q2d(data->framerate) * 8; @@ -124,6 +131,8 @@ static int rfc4175_parse_fmtp(AVFormatContext *s, AVStream *stream, data->sampling = av_strdup(value); else if (!strncmp(attr, "depth", 5)) data->depth = atoi(value); + else if (!strncmp(attr, "interlace", 9)) + data->interlaced = 1; else if (!strncmp(attr, "exactframerate", 14)) { if (av_parse_video_rate(&data->framerate, value) < 0) return AVERROR(EINVAL); @@ -195,15 +204,18 @@ static int rfc4175_parse_sdp_line(AVFormatContext *s, int st_index, static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt, int stream_index) { - int ret; + int ret = 0; pkt->stream_index = stream_index; + if (!data->interlaced || data->field) { ret = av_packet_from_data(pkt, data->frame, data->frame_size); if (ret < 0) { av_freep(&data->frame); } - data->frame = NULL; + } + + data->field = 0; return ret; } @@ -213,7 +225,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, const uint8_t * buf, int len, uint16_t seq, int flags) { - int length, line, offset, cont; + int length, line, offset, cont, field; const uint8_t *headers = buf + 2; /* skip extended seqnum */ const uint8_t *payload = buf + 2; int payload_len = len - 2; @@ -266,10 +278,12 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, return AVERROR_INVALIDDATA; length = (headers[0] << 8) | headers[1]; + field = (headers[2] & 0x80) >> 7; line = ((headers[2] & 0x7f) << 8) | headers[3]; offset = ((headers[4] & 0x7f) << 8) | headers[5]; cont = headers[4] & 0x80; headers += 6; + data->field = field; if (!data->pgroup || length % data->pgroup) return AVERROR_INVALIDDATA; @@ -277,9 +291,12 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, if (length > payload_len) length = payload_len; + if (data->interlaced) + line = 2 * line + field; + /* prevent ill-formed packets to write after buffer's end */ copy_offset = (line * data->width + offset) * data->pgroup / data->xinc; - if (copy_offset + length > data->frame_size) + if (copy_offset + length > data->frame_size || !data->frame) return AVERROR_INVALIDDATA; dest = data->frame + copy_offset; From 3ea93bbd6d9687f0171ae632c94b18199b9e62a4 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 11 Jan 2022 16:33:21 +0800 Subject: [PATCH 870/894] avformat/rtpdec_rfc4175: reindent after last commit Signed-off-by: Limin Wang --- libavformat/rtpdec_rfc4175.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index e0a708e437..8e73c07838 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -208,11 +208,11 @@ static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt, pkt->stream_index = stream_index; if (!data->interlaced || data->field) { - ret = av_packet_from_data(pkt, data->frame, data->frame_size); - if (ret < 0) { - av_freep(&data->frame); - } - data->frame = NULL; + ret = av_packet_from_data(pkt, data->frame, data->frame_size); + if (ret < 0) { + av_freep(&data->frame); + } + data->frame = NULL; } data->field = 0; From b697326a68372bec6dc3adece9afaaaebae5028d Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Sat, 1 Jan 2022 20:19:50 +0800 Subject: [PATCH 871/894] avformat/rtpenc_rfc4175: support for interlace format Below are steps how to test on your local host: wget --no-check-certificate https://samples.ffmpeg.org/MPEG2/interlaced/burosch1.mpg 1. interlace format: ffmpeg -re -i ./burosch1.mpg -c:v bitpacked -pix_fmt yuv422p10 -f rtp rtp://239.255.0.1:6000 copy and create sdp file test.sdp ffplay -buffer_size 671088640 -protocol_whitelist "file,rtp,udp" test.sdp 2. progressive format: ffmpeg -re -i ./burosch1.mpg -vf yadif -c:v bitpacked -pix_fmt yuv422p10 -f rtp rtp://239.255.0.1:6000 copy and create sdp file test.sdp ffplay -buffer_size 671088640 -protocol_whitelist "file,rtp,udp" test.sdp Signed-off-by: Limin Wang --- libavformat/rtpenc.c | 9 +++++++-- libavformat/rtpenc.h | 2 +- libavformat/rtpenc_rfc4175.c | 31 +++++++++++++++++++++---------- libavformat/sdp.c | 5 ++++- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 17f5d9d308..6be67b5885 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -622,9 +622,14 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) ff_rtp_send_jpeg(s1, pkt->data, size); break; case AV_CODEC_ID_BITPACKED: - case AV_CODEC_ID_RAWVIDEO: - ff_rtp_send_raw_rfc4175 (s1, pkt->data, size); + case AV_CODEC_ID_RAWVIDEO: { + int interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE; + + ff_rtp_send_raw_rfc4175(s1, pkt->data, size, interlaced, 0); + if (interlaced) + ff_rtp_send_raw_rfc4175(s1, pkt->data, size, interlaced, 1); break; + } case AV_CODEC_ID_OPUS: if (size > s->max_payload_size) { av_log(s1, AV_LOG_ERROR, diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index 70ea85bf3f..9c8ad14a53 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -95,7 +95,7 @@ void ff_rtp_send_vc2hq(AVFormatContext *s1, const uint8_t *buf, int size, int in void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_vp9(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buff, int size); -void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size); +void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced, int field); const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start, const uint8_t *av_restrict end); diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c index ea4c3705f3..257d072cd3 100644 --- a/libavformat/rtpenc_rfc4175.c +++ b/libavformat/rtpenc_rfc4175.c @@ -21,36 +21,40 @@ #include "avformat.h" #include "rtpenc.h" -void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) +void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced, int field) { RTPMuxContext *s = s1->priv_data; int width = s1->streams[0]->codecpar->width; int height = s1->streams[0]->codecpar->height; int xinc, yinc, pgroup; - int field = 0; int i = 0; int offset = 0; s->timestamp = s->cur_timestamp; switch (s1->streams[0]->codecpar->format) { case AV_PIX_FMT_UYVY422: - xinc = yinc = 2; + xinc = 2; + yinc = 1 << interlaced; pgroup = 4; break; case AV_PIX_FMT_YUV422P10: - xinc = yinc = 2; + xinc = 2; + yinc = 1 << interlaced; pgroup = 5; break; case AV_PIX_FMT_YUV420P: - xinc = yinc = 4; + xinc = 4; + yinc = 1 << interlaced; pgroup = 6; break; case AV_PIX_FMT_RGB24: - xinc = yinc = 1; + xinc = 1; + yinc = 1 << interlaced; pgroup = 3; break; case AV_PIX_FMT_BGR24: - xinc = yinc = 1; + xinc = 1; + yinc = 1 << interlaced; pgroup = 3; break; default: @@ -72,7 +76,9 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) headers = dest; do { - pixels = width * xinc - offset; + int l_line; + + pixels = width - offset; length = (pixels * pgroup) / xinc; left -= head_size; @@ -90,8 +96,9 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) *dest++ = length & 0xff; /* Line No */ - *dest++ = ((i >> 8) & 0x7f) | ((field << 7) & 0x80); - *dest++ = i & 0xff; + l_line = i >> interlaced; + *dest++ = ((l_line >> 8) & 0x7f) | ((field << 7) & 0x80); + *dest++ = l_line & 0xff; if (next_line) i += yinc; cont = (left > (head_size + pgroup) && i < height) ? 0x80 : 0x00; @@ -106,16 +113,20 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) } while (cont); do { + int l_field; int l_line; int l_off; int copy_offset; length = (headers[0] << 8) | headers[1]; + l_field = (headers[2] & 0x80) >> 7; l_line = ((headers[2] & 0x7f) << 8) | headers[3]; l_off = ((headers[4] & 0x7f) << 8) | headers[5]; cont = headers[4] & 0x80; headers += head_size; + if (interlaced) + l_line = 2 * l_line + l_field; copy_offset = (l_line * width + l_off) * pgroup / xinc; if (copy_offset + length > size) break; diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 2230d74742..d63a0b34c4 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -728,9 +728,12 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" "a=fmtp:%d sampling=%s; " "width=%d; height=%d; " - "depth=%d\r\n", + "depth=%d", payload_type, payload_type, pix_fmt, p->width, p->height, bit_depth); + if (p->field_order != AV_FIELD_PROGRESSIVE) + av_strlcatf(buff, size, "; interlace"); + av_strlcatf(buff, size, "\r\n"); break; } From e6b990e25d2b2f443faca10accc91e1e9b998e5a Mon Sep 17 00:00:00 2001 From: "Chen,Wenbin" Date: Fri, 12 Mar 2021 10:44:06 +0800 Subject: [PATCH 872/894] libavcodec/qsvdec.c: using queue count to unref frame MSDK vc1 and av1 sometimes output frame into the same suface, but ffmpeg-qsv assume the surface will be used only once, so it will unref the frame when it receives the output surface. Now change it to unref frame according to queue count. Signed-off-by: Wenbin Chen Signed-off-by: Haihao Xiang --- libavcodec/qsvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 08370c8a0b..d9e0fef1f1 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -570,7 +570,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, return AVERROR_BUG; } - out_frame->queued = 1; + out_frame->queued += 1; av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); } else { @@ -583,7 +583,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); - out_frame->queued = 0; + out_frame->queued -= 1; if (avctx->pix_fmt != AV_PIX_FMT_QSV) { do { From 9c58fd22269c9784f1f97d7e4a30daf4e06917f8 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Wed, 18 Sep 2019 16:19:58 +0800 Subject: [PATCH 873/894] lavf/vf_deinterlace_vaapi: flush queued frame for field in DeinterlacingBob For DeinterlacingBob mode with rate=field, the frame number of output should equal 2x input total since only intra deinterlace is used. Currently for "backward_ref = 0, rate = field", extra_delay is introduced. Due to the async without flush, frame number of output is [expected_number - 2]. Specifically, if the input only has 1 frame, the output will be empty. Add deint_vaapi_request_frame for deinterlace_vaapi, send NULL frame to flush the queued frame. For 1 frame input in Bob mode with rate=field, before patch: 0 frame; after patch: 2 frames; ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i input.h264 -an -vf deinterlace_vaapi=mode=bob:rate=field -f null - Tested-by: Mark Thompson Reviewed-by: Mark Thompson Signed-off-by: Linjie Fu Signed-off-by: Haihao Xiang --- libavfilter/vf_deinterlace_vaapi.c | 44 ++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 65f319ba9a..1304561034 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -46,6 +46,9 @@ typedef struct DeintVAAPIContext { int queue_count; AVFrame *frame_queue[MAX_REFERENCES]; int extra_delay_for_timestamps; + + int eof; + int prev_pts; } DeintVAAPIContext; static const char *deint_vaapi_mode_name(int mode) @@ -188,9 +191,11 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) void *filter_params_addr = NULL; int err, i, field, current_frame_index; - av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", - av_get_pix_fmt_name(input_frame->format), - input_frame->width, input_frame->height, input_frame->pts); + // NULL frame is used to flush the queue in field mode + if (input_frame) + av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_frame->format), + input_frame->width, input_frame->height, input_frame->pts); if (ctx->queue_count < ctx->queue_depth) { ctx->frame_queue[ctx->queue_count++] = input_frame; @@ -208,6 +213,9 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) current_frame_index = ctx->pipeline_caps.num_forward_references; input_frame = ctx->frame_queue[current_frame_index]; + if (!input_frame) + return 0; + input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; for (i = 0; i < ctx->pipeline_caps.num_forward_references; i++) forward_references[i] = (VASurfaceID)(uintptr_t) @@ -289,6 +297,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) if (ctx->field_rate == 2) { if (field == 0) output_frame->pts = 2 * input_frame->pts; + else if (ctx->eof) + output_frame->pts = 3 * input_frame->pts - ctx->prev_pts; else output_frame->pts = input_frame->pts + ctx->frame_queue[current_frame_index + 1]->pts; @@ -304,6 +314,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) break; } + ctx->prev_pts = input_frame->pts; + return err; fail: @@ -313,6 +325,25 @@ fail: return err; } +static int deint_vaapi_request_frame(AVFilterLink *link) +{ + AVFilterContext *avctx = link->src; + DeintVAAPIContext *ctx = avctx->priv; + int ret; + + if (ctx->eof) + return AVERROR_EOF; + + ret = ff_request_frame(link->src->inputs[0]); + if (ret == AVERROR_EOF && ctx->extra_delay_for_timestamps) { + ctx->eof = 1; + deint_vaapi_filter_frame(link->src->inputs[0], NULL); + } else if (ret < 0) + return ret; + + return 0; +} + static av_cold int deint_vaapi_init(AVFilterContext *avctx) { VAAPIVPPContext *vpp_ctx = avctx->priv; @@ -373,9 +404,10 @@ static const AVFilterPad deint_vaapi_inputs[] = { static const AVFilterPad deint_vaapi_outputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = &deint_vaapi_config_output, + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = &deint_vaapi_request_frame, + .config_props = &deint_vaapi_config_output, }, }; From 35a9307beb6c179a5e517c0d90d5991ed45c07ac Mon Sep 17 00:00:00 2001 From: Ming Qian Date: Tue, 4 Jan 2022 17:08:34 +0800 Subject: [PATCH 874/894] avcodec/v4l2_context: remove reinit variable Cleanup after commit 3fc72c9fc16df3b7edc329ed9eeaaa1e65976c33. Fixes coverity ticket #1497095. Reviewed-by: Andriy Gelman Signed-off-by: Ming Qian --- libavcodec/v4l2_context.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index a181f884d2..e891649f92 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -178,7 +178,7 @@ static int v4l2_handle_event(V4L2Context *ctx) V4L2m2mContext *s = ctx_to_m2mctx(ctx); struct v4l2_format cap_fmt = s->capture.format; struct v4l2_event evt = { 0 }; - int reinit, ret; + int ret; ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); if (ret < 0) { @@ -200,8 +200,7 @@ static int v4l2_handle_event(V4L2Context *ctx) return 0; } - reinit = v4l2_resolution_changed(&s->capture, &cap_fmt); - if (reinit) { + if (v4l2_resolution_changed(&s->capture, &cap_fmt)) { s->capture.height = v4l2_get_height(&cap_fmt); s->capture.width = v4l2_get_width(&cap_fmt); s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); @@ -210,28 +209,20 @@ static int v4l2_handle_event(V4L2Context *ctx) return 0; } - if (reinit) - s->reinit = 1; + s->reinit = 1; - if (reinit) { - if (s->avctx) - ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); - if (ret < 0) - av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n"); + if (s->avctx) + ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); + if (ret < 0) + av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n"); - ret = ff_v4l2_m2m_codec_reinit(s); - if (ret) { - av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n"); - return AVERROR(EINVAL); - } - goto reinit_run; + ret = ff_v4l2_m2m_codec_reinit(s); + if (ret) { + av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n"); + return AVERROR(EINVAL); } - /* dummy event received */ - return 0; - /* reinit executed */ -reinit_run: return 1; } From 8b9ef5a516dcb6327bdc15943c981ed743a09ab1 Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Tue, 11 Jan 2022 10:03:50 +0800 Subject: [PATCH 875/894] avutil/parseutils: use quadhd for Quad HD qHD is 960x540 (q stands for quarter) and QHD is 2560x1440 (Q is quad). use quadhd for QHD for abbreviation. Fix ticket#9591 Signed-off-by: Limin Wang --- libavutil/parseutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 19bbdde611..94e88e0a79 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -112,7 +112,7 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "hd480", 852, 480 }, { "hd720", 1280, 720 }, { "hd1080", 1920,1080 }, - { "qhd", 2560,1440 }, + { "quadhd", 2560,1440 }, { "2k", 2048,1080 }, /* Digital Cinema System Specification */ { "2kdci", 2048,1080 }, { "2kflat", 1998,1080 }, From c21433c9539a72c17a48b155ca4581b55e326836 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 9 Jan 2022 11:18:09 +0100 Subject: [PATCH 876/894] avcodec/mpeg4video: Split off data in a header of its own Signed-off-by: Andreas Rheinhardt --- libavcodec/ituh263enc.c | 1 - libavcodec/mpeg4data.h | 3 +- libavcodec/mpeg4video.h | 35 --------------------- libavcodec/mpeg4videodata.h | 61 +++++++++++++++++++++++++++++++++++++ libavcodec/mpeg4videodec.c | 3 ++ libavcodec/mpeg4videoenc.c | 1 + libavcodec/mpegvideo_enc.c | 1 + libavcodec/msmpeg4.c | 2 +- libavcodec/msmpeg4data.c | 2 +- 9 files changed, 69 insertions(+), 40 deletions(-) create mode 100644 libavcodec/mpeg4videodata.h diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index d944c4879f..5a7791111e 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -39,7 +39,6 @@ #include "mathops.h" #include "mpegutils.h" #include "flv.h" -#include "mpeg4video.h" #include "internal.h" /** diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h index 30179d9801..c5a2b14721 100644 --- a/libavcodec/mpeg4data.h +++ b/libavcodec/mpeg4data.h @@ -28,8 +28,7 @@ #ifndef AVCODEC_MPEG4DATA_H #define AVCODEC_MPEG4DATA_H -#include -#include "mpegvideo.h" +#include "mpeg4videodata.h" /* dc encoding for MPEG-4 */ const uint8_t ff_mpeg4_DCtab_lum[13][2] = diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index cec8b30c32..87d9c9996e 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -27,7 +27,6 @@ #include "get_bits.h" #include "mpegvideo.h" -#include "rl.h" // shapes #define RECT_SHAPE 0 @@ -118,40 +117,6 @@ typedef struct Mpeg4DecContext { int rgb; } Mpeg4DecContext; -static const uint8_t mpeg4_block_count[4] = {0, 6, 8, 12}; - -/* dc encoding for MPEG-4 */ -extern const uint8_t ff_mpeg4_DCtab_lum[13][2]; -extern const uint8_t ff_mpeg4_DCtab_chrom[13][2]; - -extern const uint16_t ff_mpeg4_intra_vlc[103][2]; -extern const int8_t ff_mpeg4_intra_level[102]; -extern const int8_t ff_mpeg4_intra_run[102]; - -extern RLTable ff_mpeg4_rl_intra; -void ff_mpeg4_init_rl_intra(void); - -/* Note this is identical to the intra rvlc except that it is reordered. */ -extern RLTable ff_rvlc_rl_inter; -extern RLTable ff_rvlc_rl_intra; - -extern const uint8_t ff_sprite_trajectory_lens[15]; -extern const uint8_t ff_mb_type_b_tab[4][2]; - -/* these matrixes will be permuted for the idct */ -extern const int16_t ff_mpeg4_default_intra_matrix[64]; -extern const int16_t ff_mpeg4_default_non_intra_matrix[64]; - -extern const uint8_t ff_mpeg4_y_dc_scale_table[32]; -extern const uint8_t ff_mpeg4_c_dc_scale_table[32]; -extern const uint16_t ff_mpeg4_resync_prefix[8]; - -extern const uint8_t ff_mpeg4_dc_threshold[8]; - -extern const uint8_t ff_mpeg4_studio_dc_luma[19][2]; -extern const uint8_t ff_mpeg4_studio_dc_chroma[19][2]; -extern const uint8_t ff_mpeg4_studio_intra[12][24][2]; - void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); diff --git a/libavcodec/mpeg4videodata.h b/libavcodec/mpeg4videodata.h new file mode 100644 index 0000000000..b20096067a --- /dev/null +++ b/libavcodec/mpeg4videodata.h @@ -0,0 +1,61 @@ +/* + * MPEG-4 encoder/decoder data. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEG4VIDEODATA_H +#define AVCODEC_MPEG4VIDEODATA_H + +#include +#include "rl.h" + +/* dc encoding for MPEG-4 */ +extern const uint8_t ff_mpeg4_DCtab_lum[13][2]; +extern const uint8_t ff_mpeg4_DCtab_chrom[13][2]; + +extern const uint16_t ff_mpeg4_intra_vlc[103][2]; +extern const int8_t ff_mpeg4_intra_level[102]; +extern const int8_t ff_mpeg4_intra_run[102]; + +extern RLTable ff_mpeg4_rl_intra; +void ff_mpeg4_init_rl_intra(void); + +/* Note this is identical to the intra rvlc except that it is reordered. */ +extern RLTable ff_rvlc_rl_inter; +extern RLTable ff_rvlc_rl_intra; + +extern const uint8_t ff_sprite_trajectory_lens[15]; +extern const uint8_t ff_mb_type_b_tab[4][2]; + +/* these matrixes will be permuted for the idct */ +extern const int16_t ff_mpeg4_default_intra_matrix[64]; +extern const int16_t ff_mpeg4_default_non_intra_matrix[64]; + +extern const uint8_t ff_mpeg4_y_dc_scale_table[32]; +extern const uint8_t ff_mpeg4_c_dc_scale_table[32]; +extern const uint16_t ff_mpeg4_resync_prefix[8]; + +extern const uint8_t ff_mpeg4_dc_threshold[8]; + +extern const uint8_t ff_mpeg4_studio_dc_luma[19][2]; +extern const uint8_t ff_mpeg4_studio_dc_chroma[19][2]; +extern const uint8_t ff_mpeg4_studio_intra[12][24][2]; + +#endif /* AVCODEC_MPEG4VIDEO_H */ diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 325593a795..37088b7a6b 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -34,6 +34,7 @@ #include "mpegvideo.h" #include "mpegvideodata.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" #include "h263.h" #include "profiles.h" #include "thread.h" @@ -56,6 +57,8 @@ static VLC studio_intra_tab[12]; static VLC studio_luma_dc; static VLC studio_chroma_dc; +static const uint8_t mpeg4_block_count[4] = { 0, 6, 8, 12 }; + static const int mb_type_b_map[4] = { MB_TYPE_DIRECT2 | MB_TYPE_L0L1, MB_TYPE_L0L1 | MB_TYPE_16x16, diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index b77653d453..8871d83281 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -28,6 +28,7 @@ #include "mpegvideo.h" #include "h263.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" #include "profiles.h" /* The uni_DCtab_* tables below contain unified bits+length tables to encode DC diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 15b6669e46..afad9c8be1 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -64,6 +64,7 @@ #include "aandcttab.h" #include "flv.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" #include "internal.h" #include "bytestream.h" #include "wmv2.h" diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index e76aec6dfc..f12586dd64 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -34,7 +34,7 @@ #include "mpegvideo.h" #include "msmpeg4.h" #include "libavutil/x86/asm.h" -#include "mpeg4video.h" +#include "mpeg4videodata.h" #include "msmpeg4data.h" #include "mpegvideodata.h" #include "vc1data.h" diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c index a3a8144664..63f30ac544 100644 --- a/libavcodec/msmpeg4data.c +++ b/libavcodec/msmpeg4data.c @@ -28,7 +28,7 @@ */ #include "h263data.h" -#include "mpeg4video.h" +#include "mpeg4videodata.h" #include "msmpeg4data.h" uint32_t ff_v2_dc_lum_table[512][2]; From 75a3268beea691c73c8bb202a2d4a6d61a97234a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 9 Jan 2022 11:58:10 +0100 Subject: [PATCH 877/894] avcodec/h264_slice, mpeg4videodec: Don't use %s to write single char Signed-off-by: Andreas Rheinhardt --- libavcodec/h264_slice.c | 4 ++-- libavcodec/mpeg4videodec.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c21004df97..f9c300bc2b 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -2168,9 +2168,9 @@ static int h264_slice_init(H264Context *h, H264SliceContext *sl, if (h->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(h->avctx, AV_LOG_DEBUG, - "slice:%d %s mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", + "slice:%d %c mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", sl->slice_num, - (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"), + (h->picture_structure == PICT_FRAME ? 'F' : h->picture_structure == PICT_TOP_FIELD ? 'T' : 'B'), sl->mb_y * h->mb_width + sl->mb_x, av_get_picture_type_char(sl->slice_type), sl->slice_type_fixed ? " fix" : "", diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 37088b7a6b..515a09d8a1 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3076,11 +3076,11 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb, if (s->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(s->avctx, AV_LOG_DEBUG, - "qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n", + "qp:%d fc:%d,%d %c size:%d pro:%d alt:%d top:%d %cpel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n", s->qscale, s->f_code, s->b_code, - s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + s->pict_type == AV_PICTURE_TYPE_I ? 'I' : (s->pict_type == AV_PICTURE_TYPE_P ? 'P' : (s->pict_type == AV_PICTURE_TYPE_B ? 'B' : 'S')), gb->size_in_bits,s->progressive_sequence, s->alternate_scan, - s->top_field_first, s->quarter_sample ? "q" : "h", + s->top_field_first, s->quarter_sample ? 'q' : 'h', s->data_partitioning, ctx->resync_marker, ctx->num_sprite_warping_points, s->sprite_warping_accuracy, 1 - s->no_rounding, s->vo_type, From 42d30c9019a6b67c56b05f1828fa04c0439a4fd0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 11:04:28 +0100 Subject: [PATCH 878/894] avcodec/mpegvideo, svq3: Remove unused next_p_frame_damaged Always zero since 4d2858deac5213eaddfdc06f98379b6325d7b953. Signed-off-by: Andreas Rheinhardt --- libavcodec/h263dec.c | 7 ------- libavcodec/mpegvideo.h | 1 - libavcodec/mpegvideo_dec.c | 1 - libavcodec/svq3.c | 8 -------- libavcodec/vc1dec.c | 7 ------- 5 files changed, 24 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 11e80cb9e9..9cc2665cac 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -603,13 +603,6 @@ retry: avctx->skip_frame >= AVDISCARD_ALL) return get_consumed_bytes(s, buf_size); - if (s->next_p_frame_damaged) { - if (s->pict_type == AV_PICTURE_TYPE_B) - return get_consumed_bytes(s, buf_size); - else - s->next_p_frame_damaged = 0; - } - if ((!s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { s->me.qpel_put = s->qdsp.put_qpel_pixels_tab; s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 1c14f5b0f0..448fe2cedc 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -342,7 +342,6 @@ typedef struct MpegEncContext { int resync_mb_y; ///< y position of last resync marker GetBitContext last_resync_gb; ///< used to search for the next resync marker int mb_num_left; ///< number of MBs left in this video packet (for partitioned Slices only) - int next_p_frame_damaged; ///< set if the next p frame is damaged, to avoid showing trashed B-frames #if FF_API_FLAG_TRUNCATED ParseContext parse_context; diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 8b625d2835..1e238bd1e1 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -132,7 +132,6 @@ do {\ s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); // Error/bug resilience - s->next_p_frame_damaged = s1->next_p_frame_damaged; s->workaround_bugs = s1->workaround_bugs; s->padding_bug_score = s1->padding_bug_score; diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index e329578af0..6f3ade8ace 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -98,7 +98,6 @@ typedef struct SVQ3Context { int has_watermark; uint32_t watermark_key; int adaptive_quant; - int next_p_frame_damaged; int h_edge_pos; int v_edge_pos; int last_frame_output; @@ -1470,13 +1469,6 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, avctx->skip_frame >= AVDISCARD_ALL) return 0; - if (s->next_p_frame_damaged) { - if (s->pict_type == AV_PICTURE_TYPE_B) - return 0; - else - s->next_p_frame_damaged = 0; - } - if (s->pict_type == AV_PICTURE_TYPE_B) { s->frame_num_offset = s->slice_num - s->prev_frame_num; diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 267d72d15b..7ed5133cfa 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -872,13 +872,6 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, goto end; } - if (s->next_p_frame_damaged) { - if (s->pict_type == AV_PICTURE_TYPE_B) - goto end; - else - s->next_p_frame_damaged = 0; - } - if ((ret = ff_mpv_frame_start(s, avctx)) < 0) { goto err; } From 67cccd442f73d8eea54660b552fe954c642f060c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 13:21:08 +0100 Subject: [PATCH 879/894] avcodec/svq3: Remove dead topright_samples_available variable, code Topright samples are always available. Signed-off-by: Andreas Rheinhardt --- libavcodec/svq3.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index 6f3ade8ace..a3f434ff8d 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -128,7 +128,6 @@ typedef struct SVQ3Context { int8_t (*intra4x4_pred_mode); unsigned int top_samples_available; - unsigned int topright_samples_available; unsigned int left_samples_available; uint8_t *edge_emu_buffer; @@ -638,15 +637,10 @@ static av_always_inline void hl_decode_mb_predict_luma(SVQ3Context *s, const int dir = s->intra4x4_pred_mode_cache[scan8[i]]; uint8_t *topright; - int nnz, tr; + int nnz; if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { - const int topright_avail = (s->topright_samples_available << i) & 0x8000; av_assert2(s->mb_y || linesize <= block_offset[i]); - if (!topright_avail) { - tr = ptr[3 - linesize] * 0x01010101u; - topright = (uint8_t *)&tr; - } else - topright = ptr + 4 - linesize; + topright = ptr + 4 - linesize; } else topright = NULL; @@ -721,7 +715,6 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) s->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF; s->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF; - s->topright_samples_available = 0xFFFF; if (mb_type == 0) { /* SKIP */ if (s->pict_type == AV_PICTURE_TYPE_P || From d0bf242d02db7d0249b69fc955ba8402b2c9cc13 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 15:19:56 +0100 Subject: [PATCH 880/894] avcodec/h264_slice: Inline H264 codec id This code is only reached by the H.264 decoder. Signed-off-by: Andreas Rheinhardt --- libavcodec/h264_slice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index f9c300bc2b..4833282191 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -998,7 +998,7 @@ static int h264_slice_header_init(H264Context *h) sps->chroma_format_idc); ff_h264chroma_init(&h->h264chroma, sps->bit_depth_chroma); ff_h264qpel_init(&h->h264qpel, sps->bit_depth_luma); - ff_h264_pred_init(&h->hpc, h->avctx->codec_id, sps->bit_depth_luma, + ff_h264_pred_init(&h->hpc, AV_CODEC_ID_H264, sps->bit_depth_luma, sps->chroma_format_idc); ff_videodsp_init(&h->vdsp, sps->bit_depth_luma); From 0a6e000d75b5f721002b4e0bb7b87700472e30b2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 15:58:07 +0100 Subject: [PATCH 881/894] avcodec/h264pred: Don't compile > 8 bit versions of VP7/8 functions VP7 and VP8 are eight bit only. Signed-off-by: Andreas Rheinhardt --- libavcodec/h264pred.c | 36 ++++++++++++++++++++++++++++------ libavcodec/h264pred_template.c | 34 ++++++-------------------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index bd0d4a3d06..731cf48ea6 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -53,6 +53,30 @@ #include "h264pred_template.c" #undef BIT_DEPTH +static void pred4x4_127_dc_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t _stride) +{ + int stride = _stride; + const uint32_t a = 0x7F7F7F7FU; + + AV_WN32A(src + 0 * stride, a); + AV_WN32A(src + 1 * stride, a); + AV_WN32A(src + 2 * stride, a); + AV_WN32A(src + 3 * stride, a); +} + +static void pred4x4_129_dc_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t _stride) +{ + int stride = _stride; + const uint32_t a = 0x81818181U; + + AV_WN32A(src + 0 * stride, a); + AV_WN32A(src + 1 * stride, a); + AV_WN32A(src + 2 * stride, a); + AV_WN32A(src + 3 * stride, a); +} + static void pred4x4_vertical_vp8_c(uint8_t *src, const uint8_t *topright, ptrdiff_t stride) { @@ -447,8 +471,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ } else {\ h->pred4x4[TM_VP8_PRED ]= FUNCD(pred4x4_tm_vp8);\ - h->pred4x4[DC_127_PRED ]= FUNCC(pred4x4_127_dc , depth);\ - h->pred4x4[DC_129_PRED ]= FUNCC(pred4x4_129_dc , depth);\ + h->pred4x4[DC_127_PRED ]= FUNCD(pred4x4_127_dc);\ + h->pred4x4[DC_129_PRED ]= FUNCD(pred4x4_129_dc);\ h->pred4x4[VERT_VP8_PRED ]= FUNCC(pred4x4_vertical , depth);\ h->pred4x4[HOR_VP8_PRED ]= FUNCC(pred4x4_horizontal , depth);\ }\ @@ -524,8 +548,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8[LEFT_DC_PRED8x8]= FUNCD(pred8x8_left_dc_rv40);\ h->pred8x8[TOP_DC_PRED8x8 ]= FUNCD(pred8x8_top_dc_rv40);\ if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred8x8[DC_127_PRED8x8]= FUNCC(pred8x8_127_dc , depth);\ - h->pred8x8[DC_129_PRED8x8]= FUNCC(pred8x8_129_dc , depth);\ + h->pred8x8[DC_127_PRED8x8]= FUNCC(pred8x8_127_dc, 8);\ + h->pred8x8[DC_129_PRED8x8]= FUNCC(pred8x8_129_dc, 8);\ }\ }\ if (chroma_format_idc <= 1) {\ @@ -547,8 +571,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, case AV_CODEC_ID_VP7:\ case AV_CODEC_ID_VP8:\ h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_tm_vp8);\ - h->pred16x16[DC_127_PRED8x8]= FUNCC(pred16x16_127_dc , depth);\ - h->pred16x16[DC_129_PRED8x8]= FUNCC(pred16x16_129_dc , depth);\ + h->pred16x16[DC_127_PRED8x8]= FUNCC(pred16x16_127_dc, 8);\ + h->pred16x16[DC_129_PRED8x8]= FUNCC(pred16x16_129_dc, 8);\ break;\ default:\ h->pred16x16[PLANE_PRED8x8 ]= FUNCC(pred16x16_plane , depth);\ diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 2b30fff70f..b5bc942a5e 100644 --- a/libavcodec/h264pred_template.c +++ b/libavcodec/h264pred_template.c @@ -111,32 +111,6 @@ static void FUNCC(pred4x4_128_dc)(uint8_t *_src, const uint8_t *topright, AV_WN4PA(src+3*stride, a); } -static void FUNCC(pred4x4_127_dc)(uint8_t *_src, const uint8_t *topright, - ptrdiff_t _stride) -{ - pixel *src = (pixel*)_src; - int stride = _stride>>(sizeof(pixel)-1); - const pixel4 a = PIXEL_SPLAT_X4((1<<(BIT_DEPTH-1))-1); - - AV_WN4PA(src+0*stride, a); - AV_WN4PA(src+1*stride, a); - AV_WN4PA(src+2*stride, a); - AV_WN4PA(src+3*stride, a); -} - -static void FUNCC(pred4x4_129_dc)(uint8_t *_src, const uint8_t *topright, - ptrdiff_t _stride) -{ - pixel *src = (pixel*)_src; - int stride = _stride>>(sizeof(pixel)-1); - const pixel4 a = PIXEL_SPLAT_X4((1<<(BIT_DEPTH-1))+1); - - AV_WN4PA(src+0*stride, a); - AV_WN4PA(src+1*stride, a); - AV_WN4PA(src+2*stride, a); - AV_WN4PA(src+3*stride, a); -} - #define LOAD_TOP_RIGHT_EDGE\ const unsigned av_unused t4 = topright[0];\ @@ -427,9 +401,11 @@ static void FUNCC(pred16x16_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\ PREDICT_16x16_DC(PIXEL_SPLAT_X4(v));\ } -PRED16x16_X(127, (1<<(BIT_DEPTH-1))-1) PRED16x16_X(128, (1<<(BIT_DEPTH-1))+0) +#if BIT_DEPTH == 8 +PRED16x16_X(127, (1<<(BIT_DEPTH-1))-1) PRED16x16_X(129, (1<<(BIT_DEPTH-1))+1) +#endif static inline void FUNCC(pred16x16_plane_compat)(uint8_t *_src, ptrdiff_t _stride, @@ -551,9 +527,11 @@ static void FUNCC(pred8x8_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\ }\ } -PRED8x8_X(127, (1<<(BIT_DEPTH-1))-1) PRED8x8_X(128, (1<<(BIT_DEPTH-1))+0) +#if BIT_DEPTH == 8 +PRED8x8_X(127, (1<<(BIT_DEPTH-1))-1) PRED8x8_X(129, (1<<(BIT_DEPTH-1))+1) +#endif static void FUNCC(pred8x16_128_dc)(uint8_t *_src, ptrdiff_t stride) { From c32f6b7f8abcfd9f671f80e423e92ee0408eaa08 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 17:24:44 +0100 Subject: [PATCH 882/894] avcodec/h264pred: Remove dead > 8 pixels checks for 8bit codecs RV40, SVQ3 and VP7/VP8 are eight-bit only, so it makes no sense to check for them in the codepath initializing > eight bit contexts. Move the codec-specific code to a switch located after the eight-bit init code where this is easily possible; and add checks to the macro to enable the compiler to remove the remaining checks when initializing bitdepths > 8 at compile-time. Signed-off-by: Andreas Rheinhardt --- libavcodec/h264pred.c | 101 ++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 64 deletions(-) diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index 731cf48ea6..2d115f7b43 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -445,56 +445,19 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, #define FUNCD(a) a ## _c #define H264_PRED(depth) \ - if(codec_id != AV_CODEC_ID_RV40){\ - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred4x4[VERT_PRED ]= FUNCD(pred4x4_vertical_vp8);\ - h->pred4x4[HOR_PRED ]= FUNCD(pred4x4_horizontal_vp8);\ - } else {\ h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - }\ h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ - if(codec_id == AV_CODEC_ID_SVQ3)\ - h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCD(pred4x4_down_left_svq3);\ - else\ h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCC(pred4x4_down_left , depth);\ h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_vp8);\ - } else\ h->pred4x4[VERT_LEFT_PRED ]= FUNCC(pred4x4_vertical_left , depth);\ h->pred4x4[HOR_UP_PRED ]= FUNCC(pred4x4_horizontal_up , depth);\ - if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) {\ h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ - } else {\ - h->pred4x4[TM_VP8_PRED ]= FUNCD(pred4x4_tm_vp8);\ - h->pred4x4[DC_127_PRED ]= FUNCD(pred4x4_127_dc);\ - h->pred4x4[DC_129_PRED ]= FUNCD(pred4x4_129_dc);\ - h->pred4x4[VERT_VP8_PRED ]= FUNCC(pred4x4_vertical , depth);\ - h->pred4x4[HOR_VP8_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - }\ - if (codec_id != AV_CODEC_ID_VP8)\ + if (depth > 8 || codec_id != AV_CODEC_ID_VP8)\ h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ - }else{\ - h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ - h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ - h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCD(pred4x4_down_left_rv40);\ - h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ - h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ - h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ - h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_rv40);\ - h->pred4x4[HOR_UP_PRED ]= FUNCD(pred4x4_horizontal_up_rv40);\ - h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ - h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ - h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ - h->pred4x4[DIAG_DOWN_LEFT_PRED_RV40_NODOWN]= FUNCD(pred4x4_down_left_rv40_nodown);\ - h->pred4x4[HOR_UP_PRED_RV40_NODOWN]= FUNCD(pred4x4_horizontal_up_rv40_nodown);\ - h->pred4x4[VERT_LEFT_PRED_RV40_NODOWN]= FUNCD(pred4x4_vertical_left_rv40_nodown);\ - }\ \ h->pred8x8l[VERT_PRED ]= FUNCC(pred8x8l_vertical , depth);\ h->pred8x8l[HOR_PRED ]= FUNCC(pred8x8l_horizontal , depth);\ @@ -516,16 +479,14 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x16_vertical , depth);\ h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x16_horizontal , depth);\ }\ - if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) {\ if (chroma_format_idc <= 1) {\ h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x8_plane , depth);\ } else {\ h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x16_plane , depth);\ }\ - } else\ - h->pred8x8[PLANE_PRED8x8]= FUNCD(pred8x8_tm_vp8);\ - if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP7 && \ - codec_id != AV_CODEC_ID_VP8) {\ + if (depth > 8 || (codec_id != AV_CODEC_ID_RV40 && \ + codec_id != AV_CODEC_ID_VP7 && \ + codec_id != AV_CODEC_ID_VP8)) { \ if (chroma_format_idc <= 1) {\ h->pred8x8[DC_PRED8x8 ]= FUNCC(pred8x8_dc , depth);\ h->pred8x8[LEFT_DC_PRED8x8]= FUNCC(pred8x8_left_dc , depth);\ @@ -547,10 +508,6 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8[DC_PRED8x8 ]= FUNCD(pred8x8_dc_rv40);\ h->pred8x8[LEFT_DC_PRED8x8]= FUNCD(pred8x8_left_dc_rv40);\ h->pred8x8[TOP_DC_PRED8x8 ]= FUNCD(pred8x8_top_dc_rv40);\ - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred8x8[DC_127_PRED8x8]= FUNCC(pred8x8_127_dc, 8);\ - h->pred8x8[DC_129_PRED8x8]= FUNCC(pred8x8_129_dc, 8);\ - }\ }\ if (chroma_format_idc <= 1) {\ h->pred8x8[DC_128_PRED8x8 ]= FUNCC(pred8x8_128_dc , depth);\ @@ -561,23 +518,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred16x16[DC_PRED8x8 ]= FUNCC(pred16x16_dc , depth);\ h->pred16x16[VERT_PRED8x8 ]= FUNCC(pred16x16_vertical , depth);\ h->pred16x16[HOR_PRED8x8 ]= FUNCC(pred16x16_horizontal , depth);\ - switch(codec_id){\ - case AV_CODEC_ID_SVQ3:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_svq3);\ - break;\ - case AV_CODEC_ID_RV40:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_rv40);\ - break;\ - case AV_CODEC_ID_VP7:\ - case AV_CODEC_ID_VP8:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_tm_vp8);\ - h->pred16x16[DC_127_PRED8x8]= FUNCC(pred16x16_127_dc, 8);\ - h->pred16x16[DC_129_PRED8x8]= FUNCC(pred16x16_129_dc, 8);\ - break;\ - default:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCC(pred16x16_plane , depth);\ - break;\ - }\ + h->pred16x16[PLANE_PRED8x8 ]= FUNCC(pred16x16_plane , depth);\ h->pred16x16[LEFT_DC_PRED8x8]= FUNCC(pred16x16_left_dc , depth);\ h->pred16x16[TOP_DC_PRED8x8 ]= FUNCC(pred16x16_top_dc , depth);\ h->pred16x16[DC_128_PRED8x8 ]= FUNCC(pred16x16_128_dc , depth);\ @@ -615,6 +556,38 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, default: av_assert0(bit_depth<=8); H264_PRED(8) + switch (codec_id) { + case AV_CODEC_ID_SVQ3: + h->pred4x4[DIAG_DOWN_LEFT_PRED] = FUNCD(pred4x4_down_left_svq3); + h->pred16x16[PLANE_PRED8x8 ] = FUNCD(pred16x16_plane_svq3); + break; + case AV_CODEC_ID_RV40: + h->pred4x4[DIAG_DOWN_LEFT_PRED] = FUNCD(pred4x4_down_left_rv40); + h->pred4x4[VERT_LEFT_PRED ] = FUNCD(pred4x4_vertical_left_rv40); + h->pred4x4[HOR_UP_PRED ] = FUNCD(pred4x4_horizontal_up_rv40); + h->pred4x4[DIAG_DOWN_LEFT_PRED_RV40_NODOWN] = FUNCD(pred4x4_down_left_rv40_nodown); + h->pred4x4[HOR_UP_PRED_RV40_NODOWN] = FUNCD(pred4x4_horizontal_up_rv40_nodown); + h->pred4x4[VERT_LEFT_PRED_RV40_NODOWN] = FUNCD(pred4x4_vertical_left_rv40_nodown); + h->pred16x16[PLANE_PRED8x8 ] = FUNCD(pred16x16_plane_rv40); + break; + case AV_CODEC_ID_VP7: + case AV_CODEC_ID_VP8: + h->pred4x4[VERT_PRED ] = FUNCD(pred4x4_vertical_vp8); + h->pred4x4[HOR_PRED ] = FUNCD(pred4x4_horizontal_vp8); + h->pred4x4[VERT_LEFT_PRED ] = FUNCD(pred4x4_vertical_left_vp8); + h->pred4x4[TM_VP8_PRED ] = FUNCD(pred4x4_tm_vp8); + h->pred4x4[VERT_VP8_PRED ] = FUNCC(pred4x4_vertical, 8); + h->pred4x4[DC_127_PRED ] = FUNCD(pred4x4_127_dc); + h->pred4x4[DC_129_PRED ] = FUNCD(pred4x4_129_dc); + h->pred4x4[HOR_VP8_PRED ] = FUNCC(pred4x4_horizontal, 8); + h->pred8x8[PLANE_PRED8x8 ] = FUNCD(pred8x8_tm_vp8); + h->pred8x8[DC_127_PRED8x8 ] = FUNCC(pred8x8_127_dc, 8); + h->pred8x8[DC_129_PRED8x8 ] = FUNCC(pred8x8_129_dc, 8); + h->pred16x16[PLANE_PRED8x8 ] = FUNCD(pred16x16_tm_vp8); + h->pred16x16[DC_127_PRED8x8] = FUNCC(pred16x16_127_dc, 8); + h->pred16x16[DC_129_PRED8x8] = FUNCC(pred16x16_129_dc, 8); + break; + } break; } From 3988016fa3ec298206b9a5347683764f06ac31c6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 18:39:29 +0100 Subject: [PATCH 883/894] avcodec/h264pred: Reindentation Signed-off-by: Andreas Rheinhardt --- libavcodec/h264pred.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index 2d115f7b43..d83ca37a69 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -445,19 +445,19 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, #define FUNCD(a) a ## _c #define H264_PRED(depth) \ - h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ - h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ - h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCC(pred4x4_down_left , depth);\ - h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ - h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ - h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ - h->pred4x4[VERT_LEFT_PRED ]= FUNCC(pred4x4_vertical_left , depth);\ - h->pred4x4[HOR_UP_PRED ]= FUNCC(pred4x4_horizontal_up , depth);\ - h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ - h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ + h->pred4x4[VERT_PRED ] = FUNCC(pred4x4_vertical, depth);\ + h->pred4x4[HOR_PRED ] = FUNCC(pred4x4_horizontal, depth);\ + h->pred4x4[DC_PRED ] = FUNCC(pred4x4_dc, depth);\ + h->pred4x4[DIAG_DOWN_LEFT_PRED ] = FUNCC(pred4x4_down_left, depth);\ + h->pred4x4[DIAG_DOWN_RIGHT_PRED] = FUNCC(pred4x4_down_right, depth);\ + h->pred4x4[VERT_RIGHT_PRED ] = FUNCC(pred4x4_vertical_right, depth);\ + h->pred4x4[HOR_DOWN_PRED ] = FUNCC(pred4x4_horizontal_down, depth);\ + h->pred4x4[VERT_LEFT_PRED ] = FUNCC(pred4x4_vertical_left, depth);\ + h->pred4x4[HOR_UP_PRED ] = FUNCC(pred4x4_horizontal_up, depth);\ + h->pred4x4[LEFT_DC_PRED ] = FUNCC(pred4x4_left_dc, depth);\ + h->pred4x4[TOP_DC_PRED ] = FUNCC(pred4x4_top_dc, depth);\ if (depth > 8 || codec_id != AV_CODEC_ID_VP8)\ - h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ + h->pred4x4[DC_128_PRED ] = FUNCC(pred4x4_128_dc, depth);\ \ h->pred8x8l[VERT_PRED ]= FUNCC(pred8x8l_vertical , depth);\ h->pred8x8l[HOR_PRED ]= FUNCC(pred8x8l_horizontal , depth);\ @@ -475,15 +475,12 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, if (chroma_format_idc <= 1) {\ h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x8_vertical , depth);\ h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x8_horizontal , depth);\ + h->pred8x8[PLANE_PRED8x8] = FUNCC(pred8x8_plane, depth);\ } else {\ h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x16_vertical , depth);\ h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x16_horizontal , depth);\ + h->pred8x8[PLANE_PRED8x8] = FUNCC(pred8x16_plane, depth);\ }\ - if (chroma_format_idc <= 1) {\ - h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x8_plane , depth);\ - } else {\ - h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x16_plane , depth);\ - }\ if (depth > 8 || (codec_id != AV_CODEC_ID_RV40 && \ codec_id != AV_CODEC_ID_VP7 && \ codec_id != AV_CODEC_ID_VP8)) { \ @@ -531,8 +528,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8l_filter_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_filter_add , depth);\ h->pred8x8l_filter_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_filter_add , depth);\ if (chroma_format_idc <= 1) {\ - h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x8_vertical_add , depth);\ - h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x8_horizontal_add , depth);\ + h->pred8x8_add[VERT_PRED8x8] = FUNCC(pred8x8_vertical_add, depth);\ + h->pred8x8_add[ HOR_PRED8x8] = FUNCC(pred8x8_horizontal_add, depth);\ } else {\ h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x16_vertical_add , depth);\ h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x16_horizontal_add , depth);\ From b263415ab7dcb0f7077fed2af4aa507b4be3e2f9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 20:13:43 +0100 Subject: [PATCH 884/894] avcodec/mpegvideo: Don't set unrestricted_mv for decoders It is write-only for them. Signed-off-by: Andreas Rheinhardt --- libavcodec/flvdec.c | 1 - libavcodec/h263dec.c | 2 -- libavcodec/intelh263dec.c | 1 - libavcodec/ituh263dec.c | 2 -- libavcodec/rv10.c | 2 -- 5 files changed, 8 deletions(-) diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c index 6258c1c0a7..2ddcf021fd 100644 --- a/libavcodec/flvdec.c +++ b/libavcodec/flvdec.c @@ -90,7 +90,6 @@ int ff_flv_decode_picture_header(MpegEncContext *s) s->h263_plus = 0; - s->unrestricted_mv = 1; s->h263_long_vectors = 0; /* PEI */ diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 9cc2665cac..ac48acf47a 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -83,13 +83,11 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) s->quant_precision = 5; s->decode_mb = ff_h263_decode_mb; s->low_delay = 1; - s->unrestricted_mv = 1; /* select sub codec */ switch (avctx->codec->id) { case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: - s->unrestricted_mv = 0; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; break; case AV_CODEC_ID_MPEG4: diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index 7c794dc5e3..58c1b63c0a 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -66,7 +66,6 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) return -1; /* SAC: off */ } s->obmc= get_bits1(&s->gb); - s->unrestricted_mv = s->obmc || s->h263_long_vectors; s->pb_frame = get_bits1(&s->gb); if (format < 6) { diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 17af5d7f89..5329e62a5e 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -1150,7 +1150,6 @@ int ff_h263_decode_picture_header(MpegEncContext *s) return -1; /* SAC: off */ } s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ - s->unrestricted_mv = s->h263_long_vectors || s->obmc; s->pb_frame = get_bits1(&s->gb); s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); @@ -1180,7 +1179,6 @@ int ff_h263_decode_picture_header(MpegEncContext *s) s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ s->h263_aic = get_bits1(&s->gb); /* Advanced Intra Coding (AIC) */ s->loop_filter= get_bits1(&s->gb); - s->unrestricted_mv = s->umvplus || s->obmc || s->loop_filter; if(s->avctx->lowres) s->loop_filter = 0; diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index d8261c34c7..0dc2c87335 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -149,7 +149,6 @@ static int rv10_decode_picture_header(MpegEncContext *s) } skip_bits(&s->gb, 3); /* ignored */ s->f_code = 1; - s->unrestricted_mv = 1; return mb_count; } @@ -298,7 +297,6 @@ static int rv20_decode_picture_header(RVDecContext *rv, int whole_size) skip_bits(&s->gb, 5); s->f_code = 1; - s->unrestricted_mv = 1; s->h263_aic = s->pict_type == AV_PICTURE_TYPE_I; s->modified_quant = 1; if (!s->avctx->lowres) From fbeb8eab44cd0ab97c42ca6f23fd067c527ef829 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 21:30:26 +0100 Subject: [PATCH 885/894] avcodec/mpeg4videodec: Avoid multiple consecutive av_log() These messages belong together, yet they can be torn apart if some other call to av_log() happens between them. Reviewed-by: Michael Niedermayer Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg4videodec.c | 59 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 515a09d8a1..737689b35b 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3276,62 +3276,63 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, continue; // no startcode if (s->avctx->debug & FF_DEBUG_STARTCODE) { - av_log(s->avctx, AV_LOG_DEBUG, "startcode: %3X ", startcode); + const char *name; if (startcode <= 0x11F) - av_log(s->avctx, AV_LOG_DEBUG, "Video Object Start"); + name = "Video Object Start"; else if (startcode <= 0x12F) - av_log(s->avctx, AV_LOG_DEBUG, "Video Object Layer Start"); + name = "Video Object Layer Start"; else if (startcode <= 0x13F) - av_log(s->avctx, AV_LOG_DEBUG, "Reserved"); + name = "Reserved"; else if (startcode <= 0x15F) - av_log(s->avctx, AV_LOG_DEBUG, "FGS bp start"); + name = "FGS bp start"; else if (startcode <= 0x1AF) - av_log(s->avctx, AV_LOG_DEBUG, "Reserved"); + name = "Reserved"; else if (startcode == 0x1B0) - av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Seq Start"); + name = "Visual Object Seq Start"; else if (startcode == 0x1B1) - av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Seq End"); + name = "Visual Object Seq End"; else if (startcode == 0x1B2) - av_log(s->avctx, AV_LOG_DEBUG, "User Data"); + name = "User Data"; else if (startcode == 0x1B3) - av_log(s->avctx, AV_LOG_DEBUG, "Group of VOP start"); + name = "Group of VOP start"; else if (startcode == 0x1B4) - av_log(s->avctx, AV_LOG_DEBUG, "Video Session Error"); + name = "Video Session Error"; else if (startcode == 0x1B5) - av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Start"); + name = "Visual Object Start"; else if (startcode == 0x1B6) - av_log(s->avctx, AV_LOG_DEBUG, "Video Object Plane start"); + name = "Video Object Plane start"; else if (startcode == 0x1B7) - av_log(s->avctx, AV_LOG_DEBUG, "slice start"); + name = "slice start"; else if (startcode == 0x1B8) - av_log(s->avctx, AV_LOG_DEBUG, "extension start"); + name = "extension start"; else if (startcode == 0x1B9) - av_log(s->avctx, AV_LOG_DEBUG, "fgs start"); + name = "fgs start"; else if (startcode == 0x1BA) - av_log(s->avctx, AV_LOG_DEBUG, "FBA Object start"); + name = "FBA Object start"; else if (startcode == 0x1BB) - av_log(s->avctx, AV_LOG_DEBUG, "FBA Object Plane start"); + name = "FBA Object Plane start"; else if (startcode == 0x1BC) - av_log(s->avctx, AV_LOG_DEBUG, "Mesh Object start"); + name = "Mesh Object start"; else if (startcode == 0x1BD) - av_log(s->avctx, AV_LOG_DEBUG, "Mesh Object Plane start"); + name = "Mesh Object Plane start"; else if (startcode == 0x1BE) - av_log(s->avctx, AV_LOG_DEBUG, "Still Texture Object start"); + name = "Still Texture Object start"; else if (startcode == 0x1BF) - av_log(s->avctx, AV_LOG_DEBUG, "Texture Spatial Layer start"); + name = "Texture Spatial Layer start"; else if (startcode == 0x1C0) - av_log(s->avctx, AV_LOG_DEBUG, "Texture SNR Layer start"); + name = "Texture SNR Layer start"; else if (startcode == 0x1C1) - av_log(s->avctx, AV_LOG_DEBUG, "Texture Tile start"); + name = "Texture Tile start"; else if (startcode == 0x1C2) - av_log(s->avctx, AV_LOG_DEBUG, "Texture Shape Layer start"); + name = "Texture Shape Layer start"; else if (startcode == 0x1C3) - av_log(s->avctx, AV_LOG_DEBUG, "stuffing start"); + name = "stuffing start"; else if (startcode <= 0x1C5) - av_log(s->avctx, AV_LOG_DEBUG, "reserved"); + name = "Reserved"; else if (startcode <= 0x1FF) - av_log(s->avctx, AV_LOG_DEBUG, "System start"); - av_log(s->avctx, AV_LOG_DEBUG, " at %d\n", get_bits_count(gb)); + name = "System start"; + av_log(s->avctx, AV_LOG_DEBUG, "startcode: %3X %s at %d\n", + startcode, name, get_bits_count(gb)); } if (startcode >= 0x120 && startcode <= 0x12F) { From c936c319bd54f097cc1d75b1ee1c407d53215d71 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jan 2022 23:23:43 +0100 Subject: [PATCH 886/894] avcodec/mpegpicture: Decrease size of encoding_error array The current size is AV_NUM_DATA_POINTERS (i.e. eight). This number is chosen in order to minimize the amount of allocations for AVFrame.extended_(data|buf) for audio; it is meaningless for video for which four is sufficient. So decrease this array in order to minimize what is copied in ff_mpeg_ref_picture() and at the places that copy a whole MpegEncContext. Also do the same for snowenc. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegpicture.h | 3 ++- libavcodec/mpegvideo_enc.c | 2 +- libavcodec/snow.h | 4 +++- libavcodec/snowenc.c | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpegpicture.h b/libavcodec/mpegpicture.h index 4bcd666797..a354c2a83c 100644 --- a/libavcodec/mpegpicture.h +++ b/libavcodec/mpegpicture.h @@ -29,6 +29,7 @@ #include "motion_est.h" #include "thread.h" +#define MPEGVIDEO_MAX_PLANES 4 #define MAX_PICTURE_COUNT 36 #define EDGE_WIDTH 16 @@ -88,7 +89,7 @@ typedef struct Picture { int reference; int shared; - uint64_t encoding_error[AV_NUM_DATA_POINTERS]; + uint64_t encoding_error[MPEGVIDEO_MAX_PLANES]; } Picture; /** diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index afad9c8be1..35f0f79d4e 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1792,7 +1792,7 @@ vbv_retry: } ff_side_data_set_encoder_stats(pkt, s->current_picture.f->quality, s->current_picture_ptr->encoding_error, - (avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0, + (avctx->flags&AV_CODEC_FLAG_PSNR) ? MPEGVIDEO_MAX_PLANES : 0, s->pict_type); if (avctx->flags & AV_CODEC_FLAG_PASS1) diff --git a/libavcodec/snow.h b/libavcodec/snow.h index 8795491cf3..f5beca66e9 100644 --- a/libavcodec/snow.h +++ b/libavcodec/snow.h @@ -35,6 +35,8 @@ #include "mpegvideo.h" #include "h264qpel.h" +#define SNOW_MAX_PLANES 4 + #define FF_ME_ITER 3 #define MID_STATE 128 @@ -188,7 +190,7 @@ typedef struct SnowContext{ AVMotionVector *avmv; unsigned avmv_size; int avmv_index; - uint64_t encoding_error[AV_NUM_DATA_POINTERS]; + uint64_t encoding_error[SNOW_MAX_PLANES]; int pred; }SnowContext; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 96b0d320bc..df31eb8132 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1858,7 +1858,7 @@ redo_frame: ff_side_data_set_encoder_stats(pkt, s->current_picture->quality, s->encoding_error, - (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0, + (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? SNOW_MAX_PLANES : 0, s->current_picture->pict_type); pkt->size = ff_rac_terminate(c, 0); From c36a5dfc8f68316f93d03081e5a367b04e1cbd3c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 7 Jan 2022 17:51:11 +0100 Subject: [PATCH 887/894] avformat/rawvideodec: check packet size Fixes: division by zero Fixes: integer overflow Fixes: 43347/clusterfuzz-testcase-minimized-ffmpeg_dem_V210X_fuzzer-5846911637127168 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: lance.lmwang@gmail.com Reviewed-by: Andreas Rheinhardt Signed-off-by: Michael Niedermayer --- libavformat/rawvideodec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 3f92211af1..7b1a534452 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -42,6 +42,7 @@ static int rawvideo_read_header(AVFormatContext *ctx) enum AVPixelFormat pix_fmt; AVStream *st; int packet_size; + int ret; st = avformat_new_stream(ctx, NULL); if (!st) @@ -62,6 +63,10 @@ static int rawvideo_read_header(AVFormatContext *ctx) avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); + ret = av_image_check_size(s->width, s->height, 0, ctx); + if (ret < 0) + return ret; + st->codecpar->width = s->width; st->codecpar->height = s->height; @@ -100,6 +105,8 @@ static int rawvideo_read_header(AVFormatContext *ctx) if (packet_size < 0) return packet_size; } + if (packet_size == 0) + return AVERROR(EINVAL); st->codecpar->format = pix_fmt; ctx->packet_size = packet_size; From 46309f262c97ec125857897df1dfb76826e538c6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 9 Jan 2022 16:39:03 +0100 Subject: [PATCH 888/894] avcodec/vp3: Don't output bogus warning It is perfectly fine to have from one to seven bits left at the end of parsing. Signed-off-by: Andreas Rheinhardt --- libavcodec/vp3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 5b9ba60f49..791e531862 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -3149,10 +3149,10 @@ static av_cold int theora_decode_init(AVCodecContext *avctx) "Unknown Theora config packet: %d\n", ptype & ~0x80); break; } - if (ptype != 0x81 && 8 * header_len[i] != get_bits_count(&gb)) + if (ptype != 0x81 && get_bits_left(&gb) >= 8U) av_log(avctx, AV_LOG_WARNING, "%d bits left in packet %X\n", - 8 * header_len[i] - get_bits_count(&gb), ptype); + get_bits_left(&gb), ptype); if (s->theora < 0x030200) break; } From 99a4d166583ba160627abf59dcff8f28c3c2d423 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 9 Jan 2022 19:45:58 +0100 Subject: [PATCH 889/894] avformat/matroskaenc: Add option to shift data to write cues at front This is similar to the faststart option of the mov muxer, yet in contrast to it it works together with reserve_index_space (the equivalent to reserved_moov_size): If the reserved space does not suffice, the data is shifted; if not, the Cues are written at the front without shifting the data. Several tests that cover (not only) this have been added. Implements #7017. Signed-off-by: Andreas Rheinhardt --- doc/muxers.texi | 9 +++ libavformat/matroskaenc.c | 42 +++++++--- libavformat/version.h | 2 +- tests/fate/matroska.mak | 32 ++++++++ tests/ref/fate/matroska-dovi-write-config7 | 49 ++++++++++++ tests/ref/fate/matroska-move-cues-to-front | 72 +++++++++++++++++ tests/ref/fate/matroska-ms-mode | 89 ++++++++++++++++++++++ 7 files changed, 283 insertions(+), 12 deletions(-) create mode 100644 tests/ref/fate/matroska-dovi-write-config7 create mode 100644 tests/ref/fate/matroska-move-cues-to-front create mode 100644 tests/ref/fate/matroska-ms-mode diff --git a/doc/muxers.texi b/doc/muxers.texi index 1ea98a69a3..c49ae3a17b 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1567,6 +1567,15 @@ A safe size for most use cases should be about 50kB per hour of video. Note that cues are only written if the output is seekable and this option will have no effect if it is not. + +@item cues_to_front +If set, the muxer will write the index at the beginning of the file +by shifting the main data if necessary. This can be combined with +reserve_index_space in which case the data is only shifted if +the initially reserved space turns out to be insufficient. + +This option is ignored if the output is unseekable. + @item default_mode This option controls how the FlagDefault of the output tracks will be set. It influences which tracks players should play by default. The default mode diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 152312102a..41b2df7dbf 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -161,6 +161,7 @@ typedef struct MatroskaMuxContext { int allow_raw_vfw; int flipped_raw_rgb; int default_mode; + int move_cues_to_front; uint32_t segment_uid[4]; } MatroskaMuxContext; @@ -566,7 +567,8 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, } static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, - mkv_cues *cues, mkv_track *tracks, int num_tracks) + const mkv_cues *cues, mkv_track *tracks, int num_tracks, + uint64_t offset) { AVIOContext *cuepoint; int ret; @@ -597,7 +599,7 @@ static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, tracks[idx].has_cue = 1; track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , tracks[idx].track_num); - put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos); + put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos + offset); put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos); if (entry->duration > 0) put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration); @@ -1984,12 +1986,14 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_void(pb, s->metadata_header_padding); } - if (mkv->reserve_cues_space) { + if (mkv->reserve_cues_space || mkv->move_cues_to_front) { if (IS_SEEKABLE(pb, mkv)) { mkv->cues_pos = avio_tell(pb); - if (mkv->reserve_cues_space == 1) - mkv->reserve_cues_space++; - put_ebml_void(pb, mkv->reserve_cues_space); + if (mkv->reserve_cues_space >= 1) { + if (mkv->reserve_cues_space == 1) + mkv->reserve_cues_space++; + put_ebml_void(pb, mkv->reserve_cues_space); + } } else mkv->reserve_cues_space = -1; } @@ -2575,25 +2579,31 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) { AVIOContext *cues = NULL; - uint64_t size; + uint64_t size, offset = 0; int length_size = 0; +redo_cues: ret = start_ebml_master_crc32(&cues, mkv); if (ret < 0) return ret; ret = mkv_assemble_cues(s->streams, cues, &mkv->cues, - mkv->tracks, s->nb_streams); + mkv->tracks, s->nb_streams, offset); if (ret < 0) { ffio_free_dyn_buf(&cues); return ret; } - if (mkv->reserve_cues_space) { + if (mkv->reserve_cues_space || mkv->move_cues_to_front) { size = avio_tell(cues); length_size = ebml_length_size(size); size += 4 + length_size; - if (mkv->reserve_cues_space < size) { + if (offset + mkv->reserve_cues_space < size) { + if (mkv->move_cues_to_front) { + offset = size - mkv->reserve_cues_space; + ffio_reset_dyn_buf(cues); + goto redo_cues; + } av_log(s, AV_LOG_WARNING, "Insufficient space reserved for Cues: " "%d < %"PRIu64". No Cues will be output.\n", @@ -2601,6 +2611,15 @@ static int mkv_write_trailer(AVFormatContext *s) ret2 = AVERROR(EINVAL); goto after_cues; } else { + if (offset) { + ret = ff_format_shift_data(s, mkv->cues_pos + mkv->reserve_cues_space, + offset); + if (ret < 0) { + ffio_free_dyn_buf(&cues); + return ret; + } + endpos += offset; + } if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { ffio_free_dyn_buf(&cues); return ret64; @@ -2623,7 +2642,7 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->reserve_cues_space) { if (size < mkv->reserve_cues_space) put_ebml_void(pb, mkv->reserve_cues_space - size); - } else + } else if (!mkv->move_cues_to_front) endpos = avio_tell(pb); } @@ -2848,6 +2867,7 @@ static const AVCodecTag additional_subtitle_tags[] = { #define FLAGS AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "reserve_index_space", "Reserve a given amount of space (in bytes) at the beginning of the file for the index (cues).", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "cues_to_front", "Move Cues (the index) to the front by shifting data if necessary", OFFSET(move_cues_to_front), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, { "cluster_size_limit", "Store at most the provided amount of bytes in a cluster. ", OFFSET(cluster_size_limit), AV_OPT_TYPE_INT , { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "cluster_time_limit", "Store at most the provided number of milliseconds in a cluster.", OFFSET(cluster_time_limit), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, { "dash", "Create a WebM file conforming to WebM DASH specification", OFFSET(is_dash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, diff --git a/libavformat/version.h b/libavformat/version.h index 77f4b46712..bd014e907e 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 #define LIBAVFORMAT_VERSION_MINOR 17 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index e117a0f6a6..fca84ecf12 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -67,6 +67,38 @@ FATE_MATROSKA_FFMPEG_FFPROBE-$(call DEMMUX, MATROSKA, MATROSKA) \ += fate-matroska-zero-length-block fate-matroska-zero-length-block: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/zero_length_block.mks matroska "-c:s copy -dash 1 -dash_track_number 2000000000 -reserve_index_space 62 -metadata_header_padding 1 -default_mode infer_no_subs" "-c:s copy" "" "-show_entries stream_tags=description" +# This mainly tests the Matroska muxer's ability to shift the data +# to create enough free space to write the Cues at the front. +# The metadata_header_padding has been chosen so that three attempts +# to write the Cues are necessary. +# It also tests writing PCM audio in both endiannesses and putting +# Cues with the same timestamp in the same CuePoint as well as +# omitting CRC-32 elements when writing Matroska. +FATE_MATROSKA-$(call ALLYES, FILE_PROTOCOL WAV_DEMUXER PCM_S24LE_DECODER \ + PCM_S24BE_ENCODER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-matroska-move-cues-to-front +fate-matroska-move-cues-to-front: CMD = transcode wav $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav matroska "-map 0 -map 0 -c:a:0 pcm_s24be -c:a:1 copy -cluster_time_limit 5 -cues_to_front yes -metadata_header_padding 7840 -write_crc32 0" "-map 0 -c copy -t 0.1" + +# This tests DOVI (reading from MP4 and Matroska and writing to Matroska) +# as well as writing the Cues at the front (by shifting data) if +# the initially reserved amount of space turns out to be insufficient. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MOV_DEMUXER \ + HEVC_DECODER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER \ + PIPE_PROTOCOL) \ + += fate-matroska-dovi-write-config7 +fate-matroska-dovi-write-config7: CMD = transcode mov $(TARGET_SAMPLES)/mov/dovi-p7.mp4 matroska "-map 0 -c copy -cues_to_front yes -reserve_index_space 40 -metadata_header_padding 64339" "-map 0 -c copy" "" "-show_entries stream_side_data_list" + +# This tests writing the MS-compatibility modes V_MS/VFW/FOURCC and A_MS/ACM. +# It furthermore tests writing the Cues at the front if the cues_to_front +# option is set and more than enough space has been reserved in advance. +# (Btw: The keyframe flags of the input video stream seem wrong.) +FATE_MATROSKA-$(call ALLYES, FILE_PROTOCOL AVI_DEMUXER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER \ + PIPE_PROTOCOL) += fate-matroska-ms-mode +fate-matroska-ms-mode: CMD = transcode avi $(TARGET_SAMPLES)/vp5/potter512-400-partial.avi matroska "-map 0 -c copy -cues_to_front yes -reserve_index_space 5000" "-map 0 -c copy -t 1" + # This test the following features of the Matroska muxer: Writing projection # stream side-data; not setting any track to default if the user requested it; # and modifying and writing colorspace properties. diff --git a/tests/ref/fate/matroska-dovi-write-config7 b/tests/ref/fate/matroska-dovi-write-config7 new file mode 100644 index 0000000000..1c1422c0e4 --- /dev/null +++ b/tests/ref/fate/matroska-dovi-write-config7 @@ -0,0 +1,49 @@ +3fa1f47c5c3d22b5c33156ff14928d6c *tests/data/fate/matroska-dovi-write-config7.matroska +72758 tests/data/fate/matroska-dovi-write-config7.matroska +#extradata 0: 116, 0x2b8d1669 +#extradata 1: 116, 0x2b8d1669 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: hevc +#dimensions 0: 1920x1080 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: video +#codec_id 1: hevc +#dimensions 1: 1920x1080 +#sar 1: 0/1 +0, -83, 0, 41, 699, 0x728548f1 +1, -83, 0, 41, 1085, 0xfb2dba82, S=1, 8 +0, -42, 167, 41, 95, 0xc0312044, F=0x0 +1, -42, 167, 41, 481, 0xf23f91d5, F=0x0 +0, 0, 83, 41, 99, 0x5e0a2221, F=0x0 +1, 0, 83, 41, 485, 0x5f7b93b2, F=0x0 +0, 42, 42, 41, 99, 0xe60e208b, F=0x0 +1, 42, 42, 41, 485, 0x8335921c, F=0x0 +0, 83, 125, 41, 99, 0xa1e422e1, F=0x0 +1, 83, 125, 41, 485, 0xc4e49472, F=0x0 +0, 125, 333, 41, 96, 0xdc762089, F=0x0 +1, 125, 333, 41, 482, 0x769c921a, F=0x0 +0, 167, 250, 41, 100, 0x89cd22a0, F=0x0 +1, 167, 250, 41, 486, 0x4aca9431, F=0x0 +0, 208, 208, 41, 100, 0x6d4521ff, F=0x0 +1, 208, 208, 41, 486, 0x3b719390, F=0x0 +0, 250, 292, 41, 99, 0x92ab22c0, F=0x0 +1, 250, 292, 41, 485, 0x83e99451, F=0x0 +0, 292, 292, 41, 95, 0xcd9020bd, F=0x0 +1, 292, 292, 41, 481, 0x44ec924e, F=0x0 +[STREAM] +[/STREAM] +[STREAM] +[SIDE_DATA] +side_data_type=DOVI configuration record +dv_version_major=1 +dv_version_minor=0 +dv_profile=7 +dv_level=4 +rpu_present_flag=1 +el_present_flag=1 +bl_present_flag=0 +dv_bl_signal_compatibility_id=6 +[/SIDE_DATA] +[/STREAM] diff --git a/tests/ref/fate/matroska-move-cues-to-front b/tests/ref/fate/matroska-move-cues-to-front new file mode 100644 index 0000000000..46effff53e --- /dev/null +++ b/tests/ref/fate/matroska-move-cues-to-front @@ -0,0 +1,72 @@ +ce15d8b7577933a057c413af505500df *tests/data/fate/matroska-move-cues-to-front.matroska +23210310 tests/data/fate/matroska-move-cues-to-front.matroska +#tb 0: 1/1000 +#media_type 0: audio +#codec_id 0: pcm_s24be +#sample_rate 0: 192000 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: pcm_s24le +#sample_rate 1: 192000 +#channel_layout 1: 3 +#channel_layout_name 1: stereo +0, 0, 0, 3, 4092, 0x71f10ea0 +1, 0, 0, 3, 4092, 0xa6320ea0 +0, 4, 4, 3, 4092, 0x51852317 +1, 4, 4, 3, 4092, 0x27732317 +0, 7, 7, 3, 4092, 0xc8e2693d +1, 7, 7, 3, 4092, 0x5899693d +0, 11, 11, 3, 4092, 0x8df13008 +1, 11, 11, 3, 4092, 0x6fa63008 +0, 14, 14, 3, 4092, 0xc56bdf7f +1, 14, 14, 3, 4092, 0x22b0df7f +0, 18, 18, 3, 4092, 0x4ac2c0f9 +1, 18, 18, 3, 4092, 0x5512c0f9 +0, 21, 21, 3, 4092, 0x11a50650 +1, 21, 21, 3, 4092, 0x11b90650 +0, 25, 25, 3, 4092, 0x0a3837f4 +1, 25, 25, 3, 4092, 0x9cb537f4 +0, 28, 28, 3, 4092, 0xff0a3ce7 +1, 28, 28, 3, 4092, 0x7d1a3ce7 +0, 32, 32, 3, 4092, 0x42d2c983 +1, 32, 32, 3, 4092, 0x0f56c983 +0, 36, 36, 3, 4092, 0x2adbf4ea +1, 36, 36, 3, 4092, 0x386bf4ea +0, 39, 39, 3, 4092, 0x86d4f0a5 +1, 39, 39, 3, 4092, 0x5924f0a5 +0, 43, 43, 3, 4092, 0x5f35d5f7 +1, 43, 43, 3, 4092, 0x565fd5f7 +0, 46, 46, 3, 4092, 0xd3f27234 +1, 46, 46, 3, 4092, 0x4d197234 +0, 50, 50, 3, 4092, 0xb3a97ff5 +1, 50, 50, 3, 4092, 0x61e67ff5 +0, 53, 53, 3, 4092, 0xce30e2ba +1, 53, 53, 3, 4092, 0xe65de2ba +0, 57, 57, 3, 4092, 0x3d482d44 +1, 57, 57, 3, 4092, 0xf85b2d44 +0, 60, 60, 3, 4092, 0x691d161c +1, 60, 60, 3, 4092, 0x3b01161c +0, 64, 64, 3, 4092, 0xe6b93525 +1, 64, 64, 3, 4092, 0xdd4e3525 +0, 67, 67, 3, 4092, 0x9ce3f785 +1, 67, 67, 3, 4092, 0x8a28f785 +0, 71, 71, 3, 4092, 0x688fc452 +1, 71, 71, 3, 4092, 0x8c5ec452 +0, 75, 75, 3, 4092, 0x400cf87e +1, 75, 75, 3, 4092, 0x1e64f87e +0, 78, 78, 3, 4092, 0x49baa923 +1, 78, 78, 3, 4092, 0x68d9a923 +0, 82, 82, 3, 4092, 0x4df27658 +1, 82, 82, 3, 4092, 0x38d77658 +0, 85, 85, 3, 4092, 0xdfebf0e7 +1, 85, 85, 3, 4092, 0xab2cf0e7 +0, 89, 89, 3, 4092, 0x69d2f76c +1, 89, 89, 3, 4092, 0x35b9f76c +0, 92, 92, 3, 4092, 0x877b89d3 +1, 92, 92, 3, 4092, 0xcc4889d3 +0, 96, 96, 3, 4092, 0x70035443 +1, 96, 96, 3, 4092, 0x04825443 +0, 99, 99, 3, 4092, 0x30135036 +1, 99, 99, 3, 4092, 0x4fba5036 diff --git a/tests/ref/fate/matroska-ms-mode b/tests/ref/fate/matroska-ms-mode new file mode 100644 index 0000000000..5fe052c39b --- /dev/null +++ b/tests/ref/fate/matroska-ms-mode @@ -0,0 +1,89 @@ +b3d928e92bc8b323793a237ce82f9437 *tests/data/fate/matroska-ms-mode.matroska +413108 tests/data/fate/matroska-ms-mode.matroska +#extradata 0: 40, 0x54290c93 +#extradata 1: 114, 0xb6c80771 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: vp5 +#dimensions 0: 512x304 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: speex +#sample_rate 1: 32000 +#channel_layout 1: 4 +#channel_layout_name 1: mono +0, 0, 0, 41, 12972, 0x6588cf8e +1, 0, 0, 0, 74, 0xd4eb274d +1, 20, 20, 0, 74, 0xef822181 +1, 40, 40, 0, 74, 0x61e3239c +0, 42, 42, 41, 478, 0xeca1eeb9 +1, 60, 60, 0, 74, 0x474623d5 +1, 80, 80, 0, 74, 0x79a21f22 +0, 83, 83, 41, 260, 0x335f8133 +1, 100, 100, 0, 74, 0xb3022058 +1, 120, 120, 0, 74, 0x57a32240 +0, 125, 125, 41, 199, 0xf6f86142 +1, 140, 140, 0, 74, 0x34892453 +1, 160, 160, 0, 74, 0x55621efb +0, 167, 167, 41, 188, 0x0eeb5f55 +1, 180, 180, 0, 74, 0xb92f206a +1, 200, 200, 0, 74, 0x1988222e +0, 209, 209, 41, 183, 0x921a5b3c +1, 220, 220, 0, 74, 0x033b20dc +1, 240, 240, 0, 74, 0xf8f41da4 +0, 250, 250, 41, 181, 0xae765703 +1, 260, 260, 0, 74, 0xfc89201f +1, 280, 280, 0, 74, 0x2b102428 +0, 292, 292, 41, 181, 0xdc975d93 +1, 300, 300, 0, 74, 0x2df42380 +1, 320, 320, 0, 74, 0xebcf20fd +0, 334, 334, 41, 181, 0x30355b73 +1, 340, 340, 0, 74, 0x3eb524f8 +1, 360, 360, 0, 74, 0x1f802308 +0, 375, 375, 41, 179, 0xef275e89 +1, 380, 380, 0, 74, 0x218d23bd +1, 400, 400, 0, 74, 0x77f82421 +0, 417, 417, 41, 181, 0xbdb35a1b +1, 420, 420, 0, 74, 0xf20023a3 +1, 440, 440, 0, 74, 0x82cc1f9a +0, 459, 459, 41, 179, 0x1b245f55 +1, 460, 460, 0, 74, 0x8d3222e4 +1, 480, 480, 0, 74, 0x939d1e4c +1, 500, 500, 0, 74, 0x55c3232c +0, 501, 501, 41, 181, 0x30355b73 +1, 520, 520, 0, 74, 0x85e02092 +1, 540, 540, 0, 74, 0xb9d02059 +0, 542, 542, 41, 179, 0xef275e89 +1, 560, 560, 0, 74, 0xbbd8211f +1, 580, 580, 0, 74, 0xe0ca20e1 +0, 584, 584, 41, 181, 0xbdb35a1b +1, 600, 600, 0, 74, 0xd4f9216b +1, 620, 620, 0, 74, 0xdea723f9 +0, 626, 626, 41, 179, 0x1b245f55 +1, 640, 640, 0, 74, 0xc2611fe9 +1, 660, 660, 0, 74, 0x9f941f2d +0, 667, 667, 41, 181, 0x30355b73 +1, 680, 680, 0, 74, 0xaf991eb9 +1, 700, 700, 0, 74, 0x7e79250e +0, 709, 709, 41, 179, 0xef275e89 +1, 720, 720, 0, 74, 0x5a421faa +1, 740, 740, 0, 74, 0x3b211ce0 +0, 751, 751, 41, 181, 0xbdb35a1b +1, 760, 760, 0, 74, 0x4a812478 +1, 780, 780, 0, 74, 0xfc1b234f +0, 792, 792, 41, 179, 0x1b245f55 +1, 800, 800, 0, 74, 0x3d561db1 +1, 820, 820, 0, 74, 0x6bbb2475 +0, 834, 834, 41, 181, 0x30355b73 +1, 840, 840, 0, 74, 0x76fe1f63 +1, 860, 860, 0, 74, 0x15861cf1 +0, 876, 876, 41, 179, 0xef275e89 +1, 880, 880, 0, 74, 0x7dca1c6a +1, 900, 900, 0, 74, 0xad8b20aa +0, 918, 918, 41, 181, 0xbdb35a1b +1, 920, 920, 0, 74, 0x6ba01e89 +1, 940, 940, 0, 74, 0x621421eb +0, 959, 959, 41, 179, 0x1b245f55 +1, 960, 960, 0, 74, 0x26672424 +1, 980, 980, 0, 74, 0xcb6120f4 From b57656e28bace8835208fec938ff82a85671941e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 9 Jan 2022 21:13:18 +0100 Subject: [PATCH 890/894] fate/matroska: Add test for QT-mode Signed-off-by: Andreas Rheinhardt --- tests/fate/matroska.mak | 6 ++ tests/ref/fate/matroska-qt-mode | 125 ++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tests/ref/fate/matroska-qt-mode diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index fca84ecf12..295489d2cc 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -99,6 +99,12 @@ FATE_MATROSKA-$(call ALLYES, FILE_PROTOCOL AVI_DEMUXER MATROSKA_MUXER \ PIPE_PROTOCOL) += fate-matroska-ms-mode fate-matroska-ms-mode: CMD = transcode avi $(TARGET_SAMPLES)/vp5/potter512-400-partial.avi matroska "-map 0 -c copy -cues_to_front yes -reserve_index_space 5000" "-map 0 -c copy -t 1" +# This tests Matroska's QT-compatibility mode. +FATE_MATROSKA-$(call ALLYES, FILE_PROTOCOL MOV_DEMUXER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-matroska-qt-mode +fate-matroska-qt-mode: CMD = transcode mov $(TARGET_SAMPLES)/svq1/marymary-shackles.mov matroska "-c copy" "-c copy -t 3" + # This test the following features of the Matroska muxer: Writing projection # stream side-data; not setting any track to default if the user requested it; # and modifying and writing colorspace properties. diff --git a/tests/ref/fate/matroska-qt-mode b/tests/ref/fate/matroska-qt-mode new file mode 100644 index 0000000000..9dc115cc0d --- /dev/null +++ b/tests/ref/fate/matroska-qt-mode @@ -0,0 +1,125 @@ +a741bd63da27d6b8ce3a21009267703d *tests/data/fate/matroska-qt-mode.matroska +1884278 tests/data/fate/matroska-qt-mode.matroska +#extradata 0: 90, 0x817d0185 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: svq1 +#dimensions 0: 160x120 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: pcm_u8 +#sample_rate 1: 22050 +#channel_layout 1: 4 +#channel_layout_name 1: mono +0, 0, 0, 66, 3340, 0xcdb26464 +1, 0, 0, 46, 1024, 0x3c0f001e +1, 46, 46, 46, 1024, 0x5772fef7 +0, 67, 67, 66, 76, 0xc93b1f74, F=0x0 +1, 93, 93, 46, 1024, 0xa98efec4 +0, 133, 133, 66, 116, 0x5688353c, F=0x0 +1, 139, 139, 46, 1024, 0xba56fd5d +1, 186, 186, 46, 1024, 0x69d7063c +0, 200, 200, 66, 112, 0xbe8f3086, F=0x0 +1, 232, 232, 46, 1024, 0x2b67fc5a +0, 267, 267, 66, 132, 0xd0cd3b9c, F=0x0 +1, 279, 279, 46, 1024, 0xcdf9022d +1, 325, 325, 46, 1024, 0x91f6fd81 +0, 333, 333, 66, 200, 0x42385725, F=0x0 +1, 372, 372, 46, 1024, 0x920eff99 +0, 400, 400, 66, 164, 0x2d344be3, F=0x0 +1, 418, 418, 46, 1024, 0x09a2ff2b +1, 464, 464, 35, 785, 0x6ece8797 +0, 467, 467, 66, 176, 0xc97c53ff, F=0x0 +1, 500, 500, 46, 1024, 0x9a50fc54 +0, 533, 533, 66, 216, 0x62fe5cf9, F=0x0 +1, 546, 546, 46, 1024, 0xc5ef006e +1, 593, 593, 46, 1024, 0x53430734 +0, 600, 600, 66, 164, 0x52564b48, F=0x0 +1, 639, 639, 46, 1024, 0xaaaff2dc +0, 667, 667, 66, 244, 0x25e16dfb, F=0x0 +1, 686, 686, 46, 1024, 0xe29a01d2 +1, 732, 732, 46, 1024, 0x4deb0411 +0, 733, 733, 66, 156, 0x6abe49bf, F=0x0 +1, 779, 779, 46, 1024, 0x4f5dfd8d +0, 800, 800, 66, 152, 0x47f84373, F=0x0 +1, 825, 825, 46, 1024, 0x4dc5fdf1 +0, 867, 867, 66, 144, 0xe0c64013, F=0x0 +1, 872, 872, 46, 1024, 0x7e0dff54 +1, 918, 918, 46, 1024, 0xde9cff3e +0, 933, 933, 66, 280, 0xa3b57919, F=0x0 +1, 964, 964, 35, 785, 0xfdb78def +0, 1000, 1000, 66, 3312, 0x45ee5b17 +1, 1000, 1000, 46, 1024, 0x5224f542 +1, 1046, 1046, 46, 1024, 0x6e61f9bc +0, 1067, 1067, 66, 324, 0x07cd8cd2, F=0x0 +1, 1093, 1093, 46, 1024, 0x5727115f +0, 1133, 1133, 66, 364, 0x101d9883, F=0x0 +1, 1139, 1139, 46, 1024, 0x1b70eccb +1, 1186, 1186, 46, 1024, 0x717f0778 +0, 1200, 1200, 66, 440, 0x4628b544, F=0x0 +1, 1232, 1232, 46, 1024, 0xf1870091 +0, 1267, 1267, 66, 7020, 0x0a137edf +1, 1279, 1279, 46, 1024, 0xca1df3a7 +1, 1325, 1325, 46, 1024, 0x5a921497 +0, 1333, 1333, 66, 5768, 0xc019d7b8, F=0x0 +1, 1372, 1372, 46, 1024, 0x0655e7bf +0, 1400, 1400, 66, 4820, 0xcc946718, F=0x0 +1, 1418, 1418, 46, 1024, 0x2a8a141c +1, 1464, 1464, 35, 785, 0xbd3a81a5 +0, 1467, 1467, 66, 6112, 0xbaf23f70, F=0x0 +1, 1500, 1500, 46, 1024, 0x54b5fc77 +0, 1533, 1533, 66, 6112, 0xc79655d0, F=0x0 +1, 1546, 1546, 46, 1024, 0x8febfbc1 +1, 1593, 1593, 46, 1024, 0x8ef8f1c1 +0, 1600, 1600, 66, 5112, 0x1d8fe26b, F=0x0 +1, 1639, 1639, 46, 1024, 0x565817aa +0, 1667, 1667, 66, 5872, 0x162eed4d, F=0x0 +1, 1686, 1686, 46, 1024, 0xfdd7ef74 +1, 1732, 1732, 46, 1024, 0x69080694 +0, 1733, 1733, 66, 5092, 0x6ce7e2aa, F=0x0 +1, 1779, 1779, 46, 1024, 0xe4a105c3 +0, 1800, 1800, 66, 5648, 0xfa739b01, F=0x0 +1, 1825, 1825, 46, 1024, 0x1397f5e1 +0, 1867, 1867, 66, 5516, 0x8a778b2b, F=0x0 +1, 1872, 1872, 46, 1024, 0xb298fc7a +1, 1918, 1918, 46, 1024, 0x2869030a +0, 1933, 1933, 66, 5088, 0xdd60e51e, F=0x0 +1, 1964, 1964, 35, 785, 0xf6a49164 +0, 2000, 2000, 66, 5808, 0x14b6e8b3, F=0x0 +1, 2000, 2000, 46, 1024, 0x668ce4db +1, 2046, 2046, 46, 1024, 0x08c71cd7 +0, 2067, 2067, 66, 4512, 0x9efdf756, F=0x0 +1, 2093, 2093, 46, 1024, 0xc682e3f3 +0, 2133, 2133, 66, 5404, 0x50ce47a2, F=0x0 +1, 2139, 2139, 46, 1024, 0x98bc11c5 +1, 2186, 2186, 46, 1024, 0x4a6ef47d +0, 2200, 2200, 66, 5732, 0x7b46abbf, F=0x0 +1, 2232, 2232, 46, 1024, 0xa6660535 +0, 2267, 2267, 66, 6936, 0x325421f1 +1, 2279, 2279, 46, 1024, 0xa1d1fd9d +1, 2325, 2325, 46, 1024, 0xf012fbf3 +0, 2333, 2333, 66, 5780, 0x8eb1d896, F=0x0 +1, 2372, 2372, 46, 1024, 0xacc00616 +0, 2400, 2400, 66, 2280, 0x3a778e69 +1, 2418, 2418, 46, 1024, 0xc8660aac +1, 2464, 2464, 35, 785, 0xe9416835 +0, 2467, 2467, 66, 1220, 0x676b10f0, F=0x0 +1, 2500, 2500, 46, 1024, 0xe31622b5 +0, 2533, 2533, 66, 1584, 0x668b6e9e, F=0x0 +1, 2546, 2546, 46, 1024, 0xc53ee0b8 +1, 2593, 2593, 46, 1024, 0xf26d1102 +0, 2600, 2600, 66, 1084, 0xbdf4ca3d, F=0x0 +1, 2639, 2639, 46, 1024, 0xd2fffa3d +0, 2667, 2667, 66, 1612, 0xd9f3817a, F=0x0 +1, 2686, 2686, 46, 1024, 0x584f0189 +1, 2732, 2732, 46, 1024, 0xb765fce5 +0, 2733, 2733, 66, 1696, 0x91ceac8b, F=0x0 +1, 2779, 2779, 46, 1024, 0x570dfe8b +0, 2800, 2800, 66, 1532, 0x0b2a7bf1, F=0x0 +1, 2825, 2825, 46, 1024, 0x2aa7ff16 +0, 2867, 2867, 66, 2072, 0x3daf2859, F=0x0 +1, 2872, 2872, 46, 1024, 0x5174fe72 +1, 2918, 2918, 46, 1024, 0x21b302d0 +0, 2933, 2933, 66, 1568, 0xbd4d7e64, F=0x0 +1, 2964, 2964, 35, 785, 0x88b67dcd From 008cc90d1a5fa85bb1b07c6d789be13b184d4d2a Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 14 Jan 2022 13:53:19 +0800 Subject: [PATCH 891/894] avcodec/libopenh264enc: support for colorspace and range information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavcodec/libopenh264enc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index de4b85c411..5b5914c2cf 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -330,6 +330,28 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) } } +#if OPENH264_VER_AT_LEAST(1, 6) + param.sSpatialLayers[0].uiVideoFormat = VF_UNDEF; + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED) { + param.sSpatialLayers[0].bVideoSignalTypePresent = true; + param.sSpatialLayers[0].bFullRange = (avctx->color_range == AVCOL_RANGE_JPEG); + } + + if (avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED) { + param.sSpatialLayers[0].bVideoSignalTypePresent = true; + param.sSpatialLayers[0].bColorDescriptionPresent = true; + } + + if (avctx->colorspace != AVCOL_SPC_UNSPECIFIED) + param.sSpatialLayers[0].uiColorMatrix = avctx->colorspace; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) + param.sSpatialLayers[0].uiColorPrimaries = avctx->color_primaries; + if (avctx->color_trc != AVCOL_TRC_UNSPECIFIED) + param.sSpatialLayers[0].uiTransferCharacteristics = avctx->color_trc; +#endif + if ((*s->encoder)->InitializeExt(s->encoder, ¶m) != cmResultSuccess) { av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); return AVERROR_UNKNOWN; From f74e90c2a087be56798c5e46f027b3284f4d465b Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 14 Jan 2022 17:48:10 +0800 Subject: [PATCH 892/894] avcodec/libopenh264enc: make the profile configuablable correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit due to the limitations set in d3a7bdd4ac54349aea9150a234478635d50ebd87, you weren't able to use main profile with OpenH264 1.8, or high profile with older versions Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavcodec/libopenh264enc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 5b5914c2cf..eb18046456 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -220,26 +220,25 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) #endif switch (s->profile) { -#if OPENH264_VER_AT_LEAST(1, 8) case FF_PROFILE_H264_HIGH: param.iEntropyCodingModeFlag = 1; av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " "select EProfileIdc PRO_HIGH in libopenh264.\n"); break; -#else case FF_PROFILE_H264_MAIN: param.iEntropyCodingModeFlag = 1; av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " "select EProfileIdc PRO_MAIN in libopenh264.\n"); break; -#endif case FF_PROFILE_H264_CONSTRAINED_BASELINE: case FF_PROFILE_UNKNOWN: + s->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; param.iEntropyCodingModeFlag = 0; av_log(avctx, AV_LOG_VERBOSE, "Using CAVLC, " "select EProfileIdc PRO_BASELINE in libopenh264.\n"); break; default: + s->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; param.iEntropyCodingModeFlag = 0; av_log(avctx, AV_LOG_WARNING, "Unsupported profile, " "select EProfileIdc PRO_BASELINE in libopenh264.\n"); @@ -251,6 +250,7 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate; param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate; param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate; + param.sSpatialLayers[0].uiProfileIdc = s->profile; #if OPENH264_VER_AT_LEAST(1, 7) if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den) { From edd305ed54dd3e16f2edc3ad150178483e67b78a Mon Sep 17 00:00:00 2001 From: Limin Wang Date: Fri, 14 Jan 2022 17:48:54 +0800 Subject: [PATCH 893/894] avcodec/libopenh264enc: set iEntropyCodingModeFlag by coder option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For high/main profile, user can choose to use cavlc by specify "-coder cavlc", for default, it'll will use cabac, if it's baseline, we'll use cavlc by specs anyway. ffmpeg -y -f lavfi -i testsrc -c:v libopenh264 -profile:v main -coder cavlc -frames:v 1 -bsf trace_headers -f null - before the patch: entropy_coding_mode_flag 0 = 1 after the patch: entropy_coding_mode_flag 0 = 0 Reviewed-by: Martin Storsjö Signed-off-by: Limin Wang --- libavcodec/libopenh264enc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index eb18046456..7c0501a2eb 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -193,7 +193,7 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) #endif param.bPrefixNalAddingCtrl = 0; param.iLoopFilterDisableIdc = !s->loopfilter; - param.iEntropyCodingModeFlag = 0; + param.iEntropyCodingModeFlag = s->coder >= 0 ? s->coder : 1; param.iMultipleThreadIdc = avctx->thread_count; /* Allow specifying the libopenh264 profile through AVCodecContext. */ @@ -221,14 +221,14 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) switch (s->profile) { case FF_PROFILE_H264_HIGH: - param.iEntropyCodingModeFlag = 1; - av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " - "select EProfileIdc PRO_HIGH in libopenh264.\n"); + av_log(avctx, AV_LOG_VERBOSE, "Using %s, " + "select EProfileIdc PRO_HIGH in libopenh264.\n", + param.iEntropyCodingModeFlag ? "CABAC" : "CAVLC"); break; case FF_PROFILE_H264_MAIN: - param.iEntropyCodingModeFlag = 1; - av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " - "select EProfileIdc PRO_MAIN in libopenh264.\n"); + av_log(avctx, AV_LOG_VERBOSE, "Using %s, " + "select EProfileIdc PRO_MAIN in libopenh264.\n", + param.iEntropyCodingModeFlag ? "CABAC" : "CAVLC"); break; case FF_PROFILE_H264_CONSTRAINED_BASELINE: case FF_PROFILE_UNKNOWN: From 7d377558a6c5f7e0592487f38bb76a8b99aada7a Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 5 Jan 2022 14:54:50 +0100 Subject: [PATCH 894/894] vf_tonemap: Fix order of planes This resulted in a dimmed tonemapping due to bad resulting luma calculation. Found by: Derek Buitenhuis Signed-off-by: Vittorio Giovara --- libavfilter/vf_tonemap.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c index 363df8034b..1285dbaa4d 100644 --- a/libavfilter/vf_tonemap.c +++ b/libavfilter/vf_tonemap.c @@ -119,18 +119,19 @@ static float mobius(float in, float j, double peak) static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, const AVPixFmtDescriptor *desc, int x, int y, double peak) { - const float *r_in = (const float *)(in->data[0] + x * desc->comp[0].step + y * in->linesize[0]); - const float *b_in = (const float *)(in->data[1] + x * desc->comp[1].step + y * in->linesize[1]); - const float *g_in = (const float *)(in->data[2] + x * desc->comp[2].step + y * in->linesize[2]); - float *r_out = (float *)(out->data[0] + x * desc->comp[0].step + y * out->linesize[0]); - float *b_out = (float *)(out->data[1] + x * desc->comp[1].step + y * out->linesize[1]); - float *g_out = (float *)(out->data[2] + x * desc->comp[2].step + y * out->linesize[2]); + int map[3] = { desc->comp[0].plane, desc->comp[1].plane, desc->comp[2].plane }; + const float *r_in = (const float *)(in->data[map[0]] + x * desc->comp[map[0]].step + y * in->linesize[map[0]]); + const float *g_in = (const float *)(in->data[map[1]] + x * desc->comp[map[1]].step + y * in->linesize[map[1]]); + const float *b_in = (const float *)(in->data[map[2]] + x * desc->comp[map[2]].step + y * in->linesize[map[2]]); + float *r_out = (float *)(out->data[map[0]] + x * desc->comp[map[0]].step + y * out->linesize[map[0]]); + float *g_out = (float *)(out->data[map[1]] + x * desc->comp[map[1]].step + y * out->linesize[map[1]]); + float *b_out = (float *)(out->data[map[2]] + x * desc->comp[map[2]].step + y * out->linesize[map[2]]); float sig, sig_orig; /* load values */ *r_out = *r_in; - *b_out = *b_in; *g_out = *g_in; + *b_out = *b_in; /* desaturate to prevent unnatural colors */ if (s->desat > 0) {